Этот вопрос, вероятно, потребует знания формата matroska. Когда я смешиваю видео и аудио вместе, аудиопакеты начинаются с временного кода 0, а видео начинается с временного кода 7. Должно ли видео с частотой 30 кадров в секунду начинаться с временного кода 0 или с временного кода 33 (для времени 0,033 временные коды указываются в миллисекундах)? Можно ли сделать так, чтобы аудио и видео начинались с таймкода 0?
Вам не нужно читать ниже, остальное просто дополнительная информация.
Я пытался добавить фильтры [v]setpts=N/(30*TB)[v];[a]asetpts=N/SR/TB[a]
в качестве двух последних фильтров, но это ничего не изменило.
Вот полная команда, которую я использую. Это просто двухпроходное кодирование vp8 для видео и однопроходное кодирование opus для аудио. Он также нарезает видео на несколько частей длиной 3 секунды и объединяет их вместе.
ffmpeg -threads 1 -i 480P_600K_71149981.mp4 -force_key_frames 00:00:03.000 -filter_complex [0:v]scale=320x180:force_original_aspect_ratio=decrease,fps=30[vid];[vid]split[vid][vid_copy];[vid_copy]trim=start=0:duration=3,setpts=PTS-STARTPTS[c0v];[0:a]atrim=start=0:duration=3,asetpts=PTS-STARTPTS[c0a];[vid]split[vid][vid_copy];[vid_copy]trim=start=90:duration=3,setpts=PTS-STARTPTS[c1v];[0:a]atrim=start=90:duration=3,asetpts=PTS-STARTPTS[c1a];[vid]split[vid][vid_copy];[vid_copy]trim=start=180:duration=3,setpts=PTS-STARTPTS[c2v];[0:a]atrim=start=180:duration=3,asetpts=PTS-STARTPTS[c2a];[vid]trim=start=270:duration=3,setpts=PTS-STARTPTS[c3v];[0:a]atrim=start=270:duration=3,asetpts=PTS-STARTPTS[c3a];[c0v][c0a][c1v][c1a][c2v][c2a][c3v][c3a]concat=n=4:v=1:a=1[v][a];[v]setpts=N/(30*TB)[v];[a]asetpts=N/SR/TB[a] -map [v] -map [a] -c:v vp8 -b:v 200k -crf 54 -profile:v 1 -an -pass 1 -passlogfile jump_passlogfile -f null NUL
ffmpeg -threads 1 -i 480P_600K_71149981.mp4 -force_key_frames 00:00:03.000 -filter_complex [0:v]scale=320x180:force_original_aspect_ratio=decrease,fps=30[vid];[vid]split[vid][vid_copy];[vid_copy]trim=start=0:duration=3,setpts=PTS-STARTPTS[c0v];[0:a]atrim=start=0:duration=3,asetpts=PTS-STARTPTS[c0a];[vid]split[vid][vid_copy];[vid_copy]trim=start=90:duration=3,setpts=PTS-STARTPTS[c1v];[0:a]atrim=start=90:duration=3,asetpts=PTS-STARTPTS[c1a];[vid]split[vid][vid_copy];[vid_copy]trim=start=180:duration=3,setpts=PTS-STARTPTS[c2v];[0:a]atrim=start=180:duration=3,asetpts=PTS-STARTPTS[c2a];[vid]trim=start=270:duration=3,setpts=PTS-STARTPTS[c3v];[0:a]atrim=start=270:duration=3,asetpts=PTS-STARTPTS[c3a];[c0v][c0a][c1v][c1a][c2v][c2a][c3v][c3a]concat=n=4:v=1:a=1[v][a];[v]setpts=N/(30*TB)[v];[a]asetpts=N/SR/TB[a] -map [v] -map [a] -c:v vp8 -b:v 200k -crf 54 -profile:v 1 -c:a libopus -b:a 32k -vbr on -compression_level 7 -ac 1 -ar 48000 -pass 2 -passlogfile jump_passlogfile -f webm -reserve_index_space 512 480P_600K_71149981_vthumb.webm
Вот файл 480P_600K_71149981.mp4, на котором я тестирую это.
И вот результат, 480P_600K_71149981_vthumb.webm и текстовый дамп его, созданный с помощью webm_parser_demo.exe
из libwebm (слегка измененный для отображения шестнадцатеричного вместо десятичного). Интересными частями текстового дампа являются поиск по «временному коду:» и "кластеру".
Cluster header: [309, 311) body: [311, 3487)
Timecode: 0
SimpleBlock header: [31a, 31c) body: [31c, 323)
track number: 2
frames: 1
timecode: 0
lacing: 0 (none)
flags: visible, key frame
frame byte range: [320, 323)
SimpleBlock header: [323, 325) body: [325, 395)
track number: 1
frames: 1
timecode: 7
lacing: 0 (none)
flags: visible, key frame
frame byte range: [329, 395)
SimpleBlock header: [395, 397) body: [397, 39e)
track number: 2
frames: 1
timecode: 15
lacing: 0 (none)
flags: visible, key frame
frame byte range: [39b, 39e)
SimpleBlock header: [39e, 3a0) body: [3a0, 3bb)
track number: 1
frames: 1
timecode: 28
lacing: 0 (none)
flags: visible
frame byte range: [3a4, 3bb)
SimpleBlock header: [3bb, 3bd) body: [3bd, 3c4)
track number: 2
frames: 1
timecode: 29
lacing: 0 (none)
flags: visible, key frame
frame byte range: [3c1, 3c4)
Исходное и конечное видео имеют разные fps, это, вероятно, важно. Существуют setpts=PTS-STARTPTS
, но они, как ни странно, не влияют на начальную временную метку презентации.
Это важно для меня, чтобы убедиться, что -force_key_frames
создает ключевой кадр в нужное время, и позже я буду использовать временные коды, чтобы оставить только 1 реплику в файле. Я просто пытаюсь отточить его, пытаюсь выучить видео форматы, пока у меня есть шанс. Я сделаю видеоплеер для тех позже, нужно, чтобы эти файлы были максимально просты для чтения и рендеринга.
Если есть только видео или только аудио, временные коды правильно начинаются с 0. Я проверил это с помощью этой команды:
ffmpeg -i 480P_600K_71149981.mp4 -t 3 -an -reserve_index_space 512 out.webm
Также мне интересно, можно ли сделать так, чтобы видеокадры шли раньше, чем аудио, это кажется более естественным способом их хранения, хотя я ни в чем не уверен. Он, вероятно, решит сам себя, как только проблема с временными метками будет решена.
Если решение требует изменения чего-либо в ffmpeg и перекомпиляции, я в порядке. Просто нужно сначала найти, что изменить.
Хотя мне интересно, должен ли я на самом деле сохранять звук перед видео и использовать -audio_preload
. Потому что для поиска звука opus я все равно должен воспроизвести миллисекунды SeekPreRoll (80 мс в моем случае). Не то чтобы меня это беспокоило, в этом случае я не собираюсь искать внутри 12-секундного видео, мне нужно только быстро извлечь ключевой кадр из второй 3-й части видео для миниатюры. Да, нет -audio_preload
здесь. Кроме того, здесь есть некоторая запутанная информация об опусном муксинге в matroska, вероятно, в этом случае бесполезная: https://wiki.xiph.org/MatroskaOpus .
Подождите, я думаю, я понял, почему видео задерживается на 7 миллисекунд. Потому что в opus вы должны проигрывать CodecDelay (здесь 6,5 мс) аудио и просто отбрасывать его, прежде чем можно будет услышать любой звук, просто для инициализации декодера. Хм, теперь мне интересно, смогу ли я установить этот отброшенный звук на отрицательную метку времени. https://www.matroska.org/technical/specs/index.html#simpleblock_structure здесь временной код представляет собой подписанный int16, так что, вероятно, я могу. Но как сказать это ffmpeg ...
Edit1: вот вывод ffprobe:
ffprobe 480P_600K_71149981_vthumb.webm -show_packets -select_streams v -read_intervals %+#5 -v 0
-
[PACKET]
codec_type=video
stream_index=0
pts=7
pts_time=0.007000
dts=7
dts_time=0.007000
duration=33
duration_time=0.033000
convergence_duration=N/A
convergence_duration_time=N/A
size=108
pos=897
flags=K_
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=40
pts_time=0.040000
dts=40
dts_time=0.040000
duration=33
duration_time=0.033000
convergence_duration=N/A
convergence_duration_time=N/A
size=23
pos=1020
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=74
pts_time=0.074000
dts=74
dts_time=0.074000
duration=33
duration_time=0.033000
convergence_duration=N/A
convergence_duration_time=N/A
size=23
pos=1067
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=107
pts_time=0.107000
dts=107
dts_time=0.107000
duration=33
duration_time=0.033000
convergence_duration=N/A
convergence_duration_time=N/A
size=23
pos=1114
flags=__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=140
pts_time=0.140000
dts=140
dts_time=0.140000
duration=33
duration_time=0.033000
convergence_duration=N/A
convergence_duration_time=N/A
size=23
pos=1152
flags=__
[/PACKET]
-
ffprobe 480P_600K_71149981_vthumb.webm -show_packets -select_streams a -read_intervals %+#5 -v 0
-
[PACKET]
codec_type=audio
stream_index=1
pts=-7
pts_time=-0.007000
dts=-7
dts_time=-0.007000
duration=20
duration_time=0.020000
convergence_duration=N/A
convergence_duration_time=N/A
size=3
pos=888
flags=K_
[/PACKET]
[PACKET]
codec_type=audio
stream_index=1
pts=14
pts_time=0.014000
dts=14
dts_time=0.014000
duration=20
duration_time=0.020000
convergence_duration=N/A
convergence_duration_time=N/A
size=3
pos=1011
flags=K_
[/PACKET]
[PACKET]
codec_type=audio
stream_index=1
pts=34
pts_time=0.034000
dts=34
dts_time=0.034000
duration=20
duration_time=0.020000
convergence_duration=N/A
convergence_duration_time=N/A
size=3
pos=1049
flags=K_
[/PACKET]
[PACKET]
codec_type=audio
stream_index=1
pts=54
pts_time=0.054000
dts=54
dts_time=0.054000
duration=20
duration_time=0.020000
convergence_duration=N/A
convergence_duration_time=N/A
size=3
pos=1058
flags=K_
[/PACKET]
[PACKET]
codec_type=audio
stream_index=1
pts=74
pts_time=0.074000
dts=74
dts_time=0.074000
duration=20
duration_time=0.020000
convergence_duration=N/A
convergence_duration_time=N/A
size=3
pos=1096
flags=K_
[/PACKET]
Действительно странно, как видео имеет первую метку времени 7, а аудио - первую метку времени -7.
В matroska (проверяется с помощью webm_parser_demo.exe
) видео имеет метку времени 7, а аудио - 0.
И моя цель - сделать первую отметку времени видео 0, а первую отметку времени аудио -7 (все данные CodecDelay).
Edit2: Изучил несколько webm с аудио vorbis
, они также не начинают оба с 0. В них аудио начинается с 0, а видео с 3. Не знаю, что с этим, это также CodecDelay?