ffmpeg可以自动对齐音频和视频轨道吗

ffmpeg可以自动对齐音频和视频轨道吗

我搜索过很多类似的问题,但不是这个问题。我试验过,但找不到答案。

我有一个独立的“数字电视转换盒”。它可以接收广播电视,并可充当 DVR。我的是“viewtv”,但有几十家不同的供应商提供。它将组合的视频和音频(以及可选的隐藏字幕/字幕)录制到 BDAV 格式文件中。我想在其他平台上观看该节目,有时编辑文件和单独的节目,而 BDAV 格式不方便(至少可以这么说)。ffmpeg 可以轻松执行将文件转换为更有用的内容的第一部分:

ffmpeg -hide_banner -err_detect ignore_err -loglevel verbose -stats -i "channel09202022-0858.mts" -map 0 -c copy "channel-09202022-0858.m2ts"

这就是我开始感到沮丧的地方。视频和音频文件之间通常存在延迟,而且每次都不一样。MediaInfo 报告了以下信息:

Audio
ID                                       : 4352 (0x1100)
Menu ID                                  : 1 (0x1)
Format                                   : AC-3
Format/Info                              : Audio Coding 3
Commercial name                          : Dolby Digital
Codec ID                                 : 129
Duration                                 : 3 h 7 min
Bit rate mode                            : Constant
Bit rate                                 : 192 kb/s
Channel(s)                               : 2 channels
Channel layout                           : L R
Sampling rate                            : 48.0 kHz
Frame rate                               : 31.250 FPS (1536 SPF)
Compression mode                         : Lossy
Delay relative to video                  : -1 s 501 ms
Stream size                              : 258 MiB (9%)
Language                                 : English
Service kind                             : Complete Main

这种延迟可能会使某些编辑程序感到困惑。如果我使用 ffmpeg 剪切片段,音频和视频就不会从同一个位置开始。我真的很想让 ffmpeg 重新同步文件,但一直无法做到。我尝试过 -vsync 和各种选项(1、2、vfr)-async 和各种选项,包括 -async 1(文档似乎表明它将同步开头)、-fflags +genpts+igndts 的各种组合、-af aresample=async=1 ,以及我能想到的所有组合。在每种情况下,ffmpeg 读取和写入时都不会报告任何错误:但新文件仍然会将“相对于视频的延迟”延续到新文件中。我为此花费了相当多的时间,而我所能展示的只是严重的烦恼。

到目前为止我发现的唯一接近的方法是转换文件一次,获取延迟的值,然后执行以下操作:

ffmpeg -err_detect ignore_err -hide_banner -loglevel info -stats -async 1 -itsoffset -1.501 -i "Story-09202022-0858.m2ts" -strict normal -map 0 -c:v copy -c:s mov_text -c:a aac -b:a 192k -ar 48000 Story-09202022-0858.mkv

这通常(但并非总是)会以一种不会在视频和音频之间显示任何明显延迟的方式重新编码音频。但是,它每次都需要手动输入值,并且必须与我所展示的完全一样。由于 -async 将被“弃用”(我看不出有什么好的理由),我尝试了本例中所谓的 -af aresample=async=1 替换,但没有奏效。

有人能告诉我是否有办法让 ffmpeg 查看文件中的信息,说明延迟是多少,然后“修复”它吗?当 off 的值已知且在文件中可用时,没有办法修复视频和音频之间的同步,这对我来说似乎很奇怪。

如果没有,是否至少有一种方法可以获取偏移量的值,以便我可以编写一个命令过程(我通常使用 Windows 来实现这一点,并且所有内容都在 BAT 文件中)来自动执行该过程?

正如我所说,我搜索过许多论坛,我发现的所有示例都与音频和视频的节奏不同、持续时间不同或类似的问题有关。除了使用 -itsoffset 之外,我从未见过修复初始偏移的示例。

如果重要的话,最终的输出将是 AVC (MP4) 视频和 AAC 音频。不幸的是,仅仅复制 AC3 中的音频是行不通的,因为有些系统(例如 DLNA 服务器和 Roku Media Player)无法正确处理它。

谢谢。

回答关于 ffprobe 的问题:您可以获得延迟,但最好的情况是您可以将输出定向到文本文件。那么您如何处理它?

我更喜欢 MediaInfo,在这种情况下它会做同样的事情:

mediainfo --Inform=Audio;%Video_Delay% "InputFile.m2ts

-666

(不,我不是在轻率,那是该特定文件的真正延迟。)

使用 ffprobe 可以完成类似的事情,但找到仅返回一个值的确切命令却非常麻烦。

无论如何,你会如何处理只有一行的文本文件

-666

在其中。如何将其转换为可以进入批处理文件中的命令行的内容?

我仍然坚持认为,既然这些数据在输入文件中,就应该有一种合理的方法让 ffmpeg 读取并使用它。

我一直在研究一些其他可能的命令,包括 -copyts、-async 1、ignpts 和 genpts 的变体、-start_at_zero 和各种 -vsync 选项,但我找不到任何可以告诉 ffmpeg 使用延迟来同步音频和视频流的东西。

答案1

使用 Linux Bash 脚本来获取延迟并在后续的 ffmpeg 命令中使用它非常简单:

我的脚本

#!/bin/bash

inputfile = $1
outputfile = ${inputfile%.m2ts}.mkv

delay = $(mediainfo --Inform=Audio;%Video_Delay% "$inputfile")

ffmpeg -err_detect ignore_err -hide_banner -loglevel info -stats \
       -async 1 -itsoffset $delay -i "${inputfile}" -strict normal \
       -map 0 -c:v copy -c:s mov_text -c:a aac -b:a 192k -ar 48000 \
       "${outputfile}"

你可以像这样运行它: myscript.bash "Story-09202022-0858.m2ts"

答案2

在某种程度上,我有点放弃了我最初的目标。但是,我找到了一个合理的解决方法。我使用 Windows 批处理文件一次处理多个文件。我使用两步过程来更改各种流在容器文件中的存储方式,这样做的副作用是(或多或少)解决了时间问题。

FOR /F "tokens=*" %%G IN ('dir /b *.mts') DO ffmpeg -hide_banner -err_detect ignore_err -loglevel info -stats -benchmark ^
 -i "%%G" -map 0 -c copy "%%~nG.m2ts"

FOR /F "tokens=*" %%G IN ('dir /b *.mts') DO ffmpeg -hide_banner -err_detect ignore_err -loglevel info -stats -benchmark ^
 -avoid_negative_ts auto -i "%%G" -i "%%G" -strict very -map 0:v -map 1:a -map 0:s:? -c:s copy -c:v copy -c:a copy "%%~nG-Step1.m2ts"

您可能想知道为什么要进行两步处理。MTS 输入文件有一个 BDAV 流,它将所有内容混合在一起。ffmpeg 和其他一些视频处理器在解释这一点时会遇到问题:例如,Avidemux 无法读取它。因此,第一步是将其复制到 M2TS 容器,该容器将流分离为单独的流。

然后,第二步再次进行复制。它读取输入文件两次:第一次包含数据,第二次读取用于从音频流中获取时间信息。这似乎使所有内容重新同步,因为在此之后我可以使用 ffmpeg 或 Avidemux 或我尝试过的任何其他东西,并且视频和音频似乎同步。

由于这两个过程“只是”复制文件而不是重新编码,因此它们运行速度非常快。到目前为止,它已经为我解决了这个问题。

相关内容