0

可能重复:
ffmpeg:转换前后的视频长度不同

最近,我一直在尝试将 FFmpeg 用于在时间参数(毫秒分辨率)方面需要非常准确的操作的应用程序。不幸的是,我惊讶地发现 FFmpeg 的操作功能返回了一些不准确的结果。

这是“ffmpeg”的输出:

ffmpeg version 0.11.1 Copyright (c) 2000-2012 the FFmpeg developers
  built on Jul 25 2012 19:55:05 with gcc 4.2.1 (Apple Inc. build 5664)
  configuration: --enable-gpl --enable-shared --enable-pthreads --enable-libx264 --enable-libmp3lame
  libavutil      51. 54.100 / 51. 54.100
  libavcodec     54. 23.100 / 54. 23.100
  libavformat    54.  6.100 / 54.  6.100
  libavdevice    54.  0.100 / 54.  0.100
  libavfilter     2. 77.100 /  2. 77.100
  libswscale      2.  1.100 /  2.  1.100
  libswresample   0. 15.100 /  0. 15.100
  libpostproc    52.  0.100 / 52.  0.100

现在,假设我想翻录“foo.mov”的音轨。这是'ffmpeg -i foo.mov'的相关输出:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'foo.mov':
  Metadata:
    major_brand     : qt  
    minor_version   : 0
    compatible_brands: qt  
    creation_time   : 2012-07-24 23:16:08
  Duration: 00:00:40.38, start: 0.000000, bitrate: 805 kb/s
    Stream #0:0(und): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p, 480x360, 733 kb/s, 24.46 fps, 29.97 tbr, 600 tbn, 1200 tbc
    Metadata:
      rotate          : 90
      creation_time   : 2012-07-24 23:16:08
      handler_name    : Core Media Data Handler
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, mono, s16, 63 kb/s
    Metadata:
      creation_time   : 2012-07-24 23:16:08
      handler_name    : Core Media Data Handler

您可能已经注意到,视频文件的持续时间是 00:00:40.38。使用以下命令,我翻录了它的音轨:

'ffmpeg -i foo.mov foo.wav'

输出:

Output #0, wav, to 'foo.wav':
  Metadata:
    major_brand     : qt  
    minor_version   : 0
    compatible_brands: qt  
    creation_time   : 2012-07-24 23:16:08
    encoder         : Lavf54.6.100
    Stream #0:0(und): Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, mono, s16, 705 kb/s
    Metadata:
      creation_time   : 2012-07-24 23:16:08
      handler_name    : Core Media Data Handler
Stream mapping:
  Stream #0:1 -> #0:0 (aac -> pcm_s16le)
Press [q] to stop, [?] for help
size=3482kB time=00:00:40.42 bitrate= 705.6kbits/s    
video:0kB audio:3482kB global headers:0kB muxing overhead 0.001290%

如您所见,输出文件比输入文件长。

另一个例子是音频(和视频)文件修剪:假设我想使用 ffmpeg 进行音频文件修剪。我使用了下一个命令:

'ffmpeg -t 00:00:10.000 -i foo.wav trimmed_foo.wav -ss 00:00:25.000'

输出:

[wav @ 0x10180e800] max_analyze_duration 5000000 reached at 5015510
Guessed Channel Layout for  Input Stream #0.0 : mono
Input #0, wav, from 'foo.wav':
  Duration: 00:00:40.42, bitrate: 705 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, mono, s16, 705 kb/s
Output #0, wav, to 'trimmed_foo.wav':
  Metadata:
    encoder         : Lavf54.6.100
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, mono, s16, 705 kb/s
Stream mapping:
  Stream #0:0 -> #0:0 (pcm_s16le -> pcm_s16le)
    Press [q] to stop, [?] for help
size=864kB time=00:00:10.03 bitrate= 705.6kbits/s    
video:0kB audio:864kB global headers:0kB muxing overhead 0.005199%

同样,输出文件比我预期的要长 30 毫秒。

很长一段时间以来,我都试图研究这个问题,但没有成功。当我将 Audacity 用于相同的功能时,它做得非常准确!

有谁知道如何解决这个问题?

4

1 回答 1

12

TL; DR : FFmpeg 和您的 iOS 设备不适合您的需求。

有很多问题需要解决,所以没有特别的顺序:

  • FFmpeg 或您正在使用的底层编解码器都不是为您想要的时间分辨率而设计的。40ms 是 25fps 的 1 帧,这在大多数视频和音频文件的上下文中并不多。超精确计时不是常见音频编解码器的设计功能,例如您的源 AAC 数据,FFmpeg 也效仿。

  • 不要进行任何转码!如果您想尽可能少地更改数据......不要更改它。您可以使用ffmpeg -i in.mov -c:a copy out.m4a精确提取音频流,而不是将其转码为 wav 格式。

  • 使用 FFprobe 而不是 FFmpeg 来获取文件信息。FFmpeg 只是提供了一些关于输入和输出文件的粗略信息,因为它的默认日志记录过于冗长。FFprobe 通常与 FFmpeg 捆绑在一起,专门设计用于以方便的形式提取信息。用于ffprobe -show_streams -show_format in.mov获取信息。

  • 增加你的-analyzeduration!您可能已经注意到max_analyze_duration reached输出中关于的注释。从文档中可以看出,在 FFmpeg估计总长度之前,实际读取文件需要多少微秒。同样,对于大多数目的而言,知道文件长度精确到微秒是不可行或不可取的,而且成本很高。如果您想要超精确度,请确保该参数设置得更高,可能比您的实际输入更长。

  • 对您的期权放置要更加小心。这是相当轻微的,但我认为我应该提出它以防你不知道。FFmpeg 的许多选项的行为不同,具体取决于它们在输入和输出方面给出的顺序。值得注意的是-ss,您正在使用。你在输入之后有它,这是你想要的,但你-t在开始时也有仅输出选项,这很奇怪。订购该命令的更自然的方式是:

    ffmpeg -i foo.wav -ss 00:00:25.000 -t 00:00:10.000 trimmed_foo.wav
    
  • 所有计时命令都接受以秒为单位的输入(包括小数秒),因此您不必在所有内容前加上00:00:.

  • 区分容器长度和实际流长度。我不使用 Audacity,但如果它显示出极高的准确性,我不会感到惊讶,因为它在对你撒谎。实际上,以毫秒精度修剪音频或视频数据不仅需要选择输入中的哪些帧包含在输出中(在 25fps 时精确到 40ms!),还需要更改帧数据以在末尾插入静音。更容易的是仅根据帧包含进行修剪,然后将超准确的长度放入容器文件元数据中。一些播放软件实际上可能会根据该数字切断,但同样,大多数 AV 软件并不是为这种精度水平而设计的。我很想知道 FFmpeg 显示为 Audacity 修剪的文件的长度。

这就是现在想到的所有内容,但是一旦您有机会整合上述一些内容,我很乐意提供更多反馈。我的猜测是研究目的需要这种准确性,在这种情况下,快乐的研究!

于 2012-07-27T19:33:36.687 回答