Точный выбор звука

Как выбрать звук, соответствующий набору выбранных фильтром видеокадров?

Например, на данный момент я сэмплирую 1 из каждых 100 кадров видео (с частотой 15 кадров в секунду), используя selectфильтр FFMpeg. Когда я пытаюсь выбрать звук этих кадров с помощью aselectфильтра, общая продолжительность звука не равна продолжительности видео (разница в 2 или 3 секунды в зависимости от того, какие кадры я выбрал). Частота дискретизации звука указана как 22050 Гц.

Я пробовал использовать различные -vsyncи -asyncкомбинации, но это не имело никакого значения. Есть ли более точный способ использования aselect?

Быстрый пример команды:

ffmpeg -i %INPUT% -vf select='between(n\,200\,399)',setpts='PTS-STARTPTS' -af aselect='between(n\,200\,399)',asetpts='PTS-STARTPTS'-y test.mkv

где «INPUT» — это имя файла, содержащего сжатое видео и аудио. Я тестирую файл AV36_1.avi, найденный на этом сайте, где размещены образцы видео. Я получаю продолжительность видео 13,3 секунды и продолжительность звука 12 секунд.

вывод:

ffmpeg version N-77045-ga16243a Copyright (c) 2000-2015 the FFmpeg developers
  built with gcc 5.2.0 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-av
isynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enab
le-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --
enable-libdcadec --enable-libfreetype --enable-libgme --enable-libgsm --enable-l
ibilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enab
le-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --en
able-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --ena
ble-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc
 --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enabl
e-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --
enable-lzma --enable-decklink --enable-zlib
  libavutil      55.  9.100 / 55.  9.100
  libavcodec     57. 16.101 / 57. 16.101
  libavformat    57. 19.100 / 57. 19.100
  libavdevice    57.  0.100 / 57.  0.100
  libavfilter     6. 20.100 /  6. 20.100
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
  libpostproc    54.  0.100 / 54.  0.100
Guessed Channel Layout for  Input Stream #0.1 : stereo
Input #0, avi, from 'AV36_1.avi':
  Duration: 00:00:32.93, start: 0.000000, bitrate: 2372 kb/s
    Stream #0:0: Video: indeo5 (IV50 / 0x30355649), yuv410p, 320x240, 2058 kb/s,
 15 fps, 15 tbr, 15 tbn, 15 tbc
    Metadata:
      title           : Steyr.avi ┬ΦΣσε #1
    Stream #0:1: Audio: adpcm_ms ([2][0][0][0] / 0x0002), 22050 Hz, 2 channels,
s16, 176 kb/s
    Metadata:
      title           : Sound Forge 4.0 Audio
Output #0, avi, to 'test.avi':
  Metadata:
    ISFT            : Lavf57.19.100
    Stream #0:0: Video: mpeg4 (FMP4 / 0x34504D46), yuv420p, 320x240, q=2-31, 200
 kb/s, 15 fps, 15 tbn, 15 tbc
    Metadata:
      title           : Steyr.avi ┬ΦΣσε #1
      encoder         : Lavc57.16.101 mpeg4
    Stream #0:1: Audio: mp3 (libmp3lame) (U[0][0][0] / 0x0055), 22050 Hz, stereo
, s16p
    Metadata:
      title           : Sound Forge 4.0 Audio
      encoder         : Lavc57.16.101 libmp3lame
Stream mapping:
  Stream #0:0 -> #0:0 (indeo5 (native) -> mpeg4 (native))
  Stream #0:1 -> #0:1 (adpcm_ms (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
frame=   98 fps=0.0 q=9.6 size=     294kB time=00:00:09.03 bitrate= 266.1kbits/s
frame=  200 fps=0.0 q=11.7 Lsize=     525kB time=00:00:13.33 bitrate= 322.5kbits
/s
video:429kB audio:72kB subtitle:0kB other streams:0kB global headers:0kB muxing
overhead: 4.625268%

Я думаю, что неправильно использую фильтр aselect...

Вставьте используемую командную строку и вывод консоли.
@Mulvya готово :)
Пожалуйста, переформатируйте консоль правильно, как первое поле здесь .
Ваша команда выбирает все кадры с # 200 по # 399, а не 1 из 100, и ваш файл образца указан как «Очень странный образец avi, содержащий какой-то случайный СПИСОК, исправленный r20118». Возможно, попробуйте с нормальным образцом. вечером проверю себя и вернусь
Точный выбор не имеет значения, дело в том, что соответствующий выбор аудио имеет большое несоответствие продолжительности. Этот тривиальный пример должен включать в себя меньше возможных осложнений, чем более сложный выбор кадров (например not(mod(n,100)) -vsync 0). Также было бы сложнее выбрать соответствующие звуковые кадры.
Похоже на известную проблему: superuser.com/q/866144/114058
@Mulvya Тем временем я думаю, что обнаружил, что это из-за разницы в частоте кадров звука. Я предположил, что она равна частоте кадров видео. Проблема в вашей ссылке предполагает, что частота кадров звука составляет 48 кадров в секунду, потому что частота дискретизации составляла 48 кГц. Но кажется, что оба предположения опасны. В этом случае частота кадров аудио составляет около 21,8 кадров в секунду. Корректируя aselectкадры с коэффициентом, 21.8/15я получаю гораздо более точную звуковую дорожку. Разница в несколько миллисекунд. :D
Если aselect использует звуковые кадры для справки, попробуйте 22.05/15, и если это сделает его более точным
@Mulvya Нет, частота кадров звука не 22,05 кадра в секунду. По данным ffprobe это 22311/1024.

Ответы (1)

Эта команда, которая использовала tссылку для aselect, работала для меня:

ffmpeg -i AV36_1.avi -vf "select=between(n\,200\,399),setpts=PTS-STARTPTS" -af "aselect=between(t\,(200/15)\,(399/15)),asetpts=PTS-STARTPTS" -y test.mkv

Если вы хотите использовать n(кадры), вам нужно будет знать размер кадра аудиокодека, например, 1024 семпла для AAC, переменный для MP3 и т. д.

Круто, но это преобразование не будет работать, если у видео переменная частота кадров. Интересна информация о размерах выборки аудиокадров, я думал, что частота дискретизации (в данном случае 22050 Гц) всегда была постоянной во времени.
Частота дискретизации постоянна, но сжатые аудиопотоки разбивают nсэмплы на фрагменты, framesкоторые не соответствуют границам видеокадра. Ваш метод также не будет работать для VFR, так как частота кадров звука, которую вы получаете от ffprobe, равна CFR. Путь к общему решению состоит в том, чтобы получить PTS первого и последнего выбранных видеокадров, а затем предоставить эквивалентное время фильтру aselect.
Тогда кажется, что временные метки - самый безопасный способ. Так будет ли кадр mp3 со 100 сэмплами длиться в 10 раз дольше, чем кадр с 10 семплами? Если aselectможно выбрать только целые аудиокадры, это может ограничить точность. Но моя интуиция подсказывает мне, что aselectвместо кадров выбираются сэмплы (по крайней мере, при использовании временных меток).
Нет. Зависит от частоты дискретизации. Если у вас частота 48000 Гц, то типичный кадр MP3 из 1152 сэмплов составляет 0,04166 секунды звука. Если 24000 Гц, то 0,0833 с.
но типичного кадра MP3 не существует, так как они имеют переменный размер кадра ... поэтому некоторые кадры будут иметь 1500 сэмплов, другие 900 и т. д. Ах, но временные метки могут быть не такими линейными, как с видео.