You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在AWS Lambda上用FFmpeg处理Mobile Safari录制视频仅输出约0.5秒

Mobile Safari录制视频转码后仅约0.5秒的原因及解决方法

问题描述

在AWS Lambda上使用Node.js结合fluent-ffmpeg处理视频转码时,多数设备/浏览器录制的视频均可正常转码,但处理Mobile Safari录制的视频时,无论输入时长多少,输出视频长度始终约为0.5秒。

转码代码(TypeScript)

import * as ffmpeg from 'fluent-ffmpeg';
public static StandardizeVideoFormat(
  inputSignedUrl: string,
  filename: string,
): Promise<string> {
  const localFilePath = `/tmp/${Date.now()}_${filename}.mp4`;

  return new Promise((resolve, reject) => {
    ffmpeg(inputSignedUrl)
      .outputOptions([
        '-crf',
        '18',
        '-vcodec',
        'libx264',
        '-codec:a',
        'aac',
        '-preset',
        'medium',
      ])
      .output(localFilePath)
      .on('start', function (commandLine) {
        console.log('Spawned Ffmpeg with command: ' + commandLine);
      })
      .on('error', function (err) {
        reject(err);
      })
      .on('progress', function (progress) {
        console.log('progress', progress);
      })
      .on('end', function () {
        resolve(localFilePath);
      })
      .run();
  });
}

输入文件FFprobe元数据

{
  streams: [
    {
      index: 0,
      codec_name: 'h264',
      codec_long_name: 'H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10',
      profile: 'Baseline',
      codec_type: 'video',
      codec_tag_string: 'avc1',
      codec_tag: '0x31637661',
      width: 1920,
      height: 1080,
      coded_width: 1920,
      coded_height: 1080,
      closed_captions: 0,
      film_grain: 0,
      has_b_frames: 0,
      sample_aspect_ratio: 'N/A',
      display_aspect_ratio: 'N/A',
      pix_fmt: 'yuvj420p',
      level: 40,
      color_range: 'pc',
      color_space: 'unknown',
      color_transfer: 'unknown',
      color_primaries: 'unknown',
      chroma_location: 'left',
      field_order: 'progressive',
      refs: 1,
      is_avc: 'true',
      nal_length_size: 4,
      id: '0x1',
      r_frame_rate: '30000/1001',
      avg_frame_rate: '60000/1991',
      time_base: '1/600',
      start_pts: 26,
      start_time: 0.043333,
      duration_ts: 4008,
      duration: 6.68,
      bit_rate: 10175170,
      max_bit_rate: 'N/A',
      bits_per_raw_sample: 8,
      nb_frames: 'N/A',
      nb_read_frames: 'N/A',
      nb_read_packets: 'N/A',
      extradata_size: 31,
      side_data_type: 'Display Matrix',
      displaymatrix: '',
      rotation: '-90',
      tags: [Object],
      disposition: [Object]
    },
    {
      index: 1,
      codec_name: 'aac',
      codec_long_name: 'AAC (Advanced Audio Coding)',
      profile: 'LC',
      codec_type: 'audio',
      codec_tag_string: 'mp4a',
      codec_tag: '0x6134706d',
      sample_fmt: 'fltp',
      sample_rate: 48000,
      channels: 1,
      channel_layout: 'mono',
      bits_per_sample: 0,
      initial_padding: 0,
      id: '0x2',
      r_frame_rate: '0/0',
      avg_frame_rate: '0/0',
      time_base: '1/48000',
      start_pts: 0,
      start_time: 0,
      duration_ts: 319488,
      duration: 6.656,
      bit_rate: 181302,
      max_bit_rate: 'N/A',
      bits_per_raw_sample: 'N/A',
      nb_frames: 'N/A',
      nb_read_frames: 'N/A',
      nb_read_packets: 'N/A',
      extradata_size: 2,
      tags: [Object],
      disposition: [Object]
    }
  ],
  format: {
    filename: 'input.mp4',
    nb_streams: 2,
    nb_programs: 0,
    format_name: 'mov,mp4,m4a,3gp,3g2,mj2',
    format_long_name: 'QuickTime / MOV',
    start_time: 0,
    duration: 6.723333,
    size: 8651792,
    bit_rate: 10294646,
    probe_score: 100,
    tags: {
      major_brand: 'iso5',
      minor_version: '1',
      compatible_brands: 'isomiso5hlsf',
      creation_time: '2023-08-05T19:03:15.000000Z'
    }
  },
  chapters: []
}

原因分析

从FFprobe元数据的format.tags.compatible_brands字段可以看到hlsf标识,说明Mobile Safari录制的视频是分段式MP4(Fragmented MP4)——这类文件采用HLS分段封装,视频数据被拆分成多个小片段存储。

FFmpeg默认的probesize(探针大小)和analyzeduration(分析时长)参数较小,不足以扫描完整的分段文件结构,导致FFmpeg仅读取了第一个视频片段(约0.5秒)就停止解析,最终输出截断后的视频。

解决方法

1. 添加输入选项,增大探针大小和分析时长

给FFmpeg添加输入选项,让它能读取足够多的文件内容以识别完整的视频结构:

.inputOptions([
  '-probesize 100M',
  '-analyzeduration 100M'
])

2. 添加输出选项优化文件结构

针对分段MP4的特性,添加-movflags +faststart输出选项,将输出文件的moov原子移到文件开头,既优化播放体验,也能辅助FFmpeg正确处理输入的分段结构。

修改后的完整代码

import * as ffmpeg from 'fluent-ffmpeg';
public static StandardizeVideoFormat(
  inputSignedUrl: string,
  filename: string,
): Promise<string> {
  const localFilePath = `/tmp/${Date.now()}_${filename}.mp4`;

  return new Promise((resolve, reject) => {
    ffmpeg(inputSignedUrl)
      // 添加输入选项,确保FFmpeg能识别完整的分段文件
      .inputOptions([
        '-probesize 100M',
        '-analyzeduration 100M'
      ])
      .outputOptions([
        '-crf', '18',
        '-vcodec', 'libx264',
        '-codec:a', 'aac',
        '-preset', 'medium',
        // 优化输出MP4的结构,同时辅助处理分段输入
        '-movflags +faststart'
      ])
      .output(localFilePath)
      .on('start', function (commandLine) {
        console.log('Spawned Ffmpeg with command: ' + commandLine);
      })
      .on('error', function (err) {
        reject(err);
      })
      .on('progress', function (progress) {
        console.log('progress', progress);
      })
      .on('end', function () {
        resolve(localFilePath);
      })
      .run();
  });
}

额外尝试方案

如果上述方法无效,可以添加-fflags +genpts输入选项,强制FFmpeg生成连续的时间戳,解决分段视频的时间戳不连续问题:

.inputOptions([
  '-probesize 100M',
  '-analyzeduration 100M',
  '-fflags +genpts'
])

内容的提问来源于stack exchange,提问作者user1825257

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 16:24:56