игнорировать «channel_layout» при работе с многоканальным звуком в ffmpeg

#ffmpeg

#ffmpeg

Вопрос:

Я работаю с многоканальными аудиофайлами (аудиофайлами более высокого порядка), которые обычно имеют не менее 16 каналов.

Иногда меня интересует только подмножество аудиоканалов (например, первые 25 каналов файла, который содержит еще больше каналов).

Для этого у меня есть сценарий, подобный следующему, который принимает многоканальный входной файл, выходной файл и количество каналов, которые я хочу извлечь:

 #!/bin/sh
infile=$1
outfile=$2
channels=$3

channelmap=$(seq -s"|" 0 $((channels-1)))

ffmpeg -y -hide_banner 
  -i "${infile}" 
  -filter_complex "[0:a]channelmap=${channelmap}" 
  -c:a  libopus -mapping_family 255 -b:a 160k -sample_fmt s16 -vn -f webm -dash 1 
  "${outfile}"
 

Фактическое извлечение канала выполняется с помощью фильтра channelmap, который вызывается с помощью чего-то вроде -filter:complex "[0:a]channelmap=0|1|2|3"

Это отлично работает с 1,2,4 или 16 каналами.

Однако он терпит неудачу с 9 каналами, 25 и 17 (и, как правило, с >> 16 каналами).

Ошибка, которую я получаю,:

 $ ffmpeg -y -hide_banner -i input.wav  -filter_complex "[0:a]channelmap=0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16" -c:a libopus -mapping_family 255 -b:a 160k  -sample_fmt s16 -vn -f webm -dash 1 output.webm
Input #0, wav, from 'input.wav':
  Duration: 00:00:09.99, bitrate: 17649 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, 25 channels, s16, 17640 kb/s
[Parsed_channelmap_0 @ 0x5568874ffbc0] Output channel layout is not set and cannot be guessed from the maps.
[AVFilterGraph @ 0x5568874fff40] Error initializing filter 'channelmap' with args '0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16'
Error initializing complex filters.
Invalid argument
 

Таким образом, ffmpeg не может угадать расположение каналов для 17-канального файла.
ffmpeg -layouts отображаются только макеты каналов с 1,2,3,4,5,6,7,8 и 16.

Однако меня действительно не волнует расположение каналов. Вся концепция «компоновки каналов» сосредоточена вокруг идеи, что каждый аудиоканал должен передаваться на другой динамик. Но мои аудиоканалы вообще не являются каналами динамиков.

Итак, я попытался предоставить явные макеты каналов с чем-то вроде -filter_complex "[0:a]channelmap=map=0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16:channel_layout=unknown" , но это приводит к ошибке при разборе макета канала:

 $ ffmpeg -y -hide_banner -i input.wav  -filter_complex "[0:a]channelmap=map=0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16:channel_layout=unknown" -c:a  libopus -mapping_family 255 -b:a 160k  -sample_fmt s16 -vn -f webm -dash 1 output.webm
Input #0, wav, from 'input.wav':
  Duration: 00:00:09.99, bitrate: 17649 kb/s
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, 25 channels, s16, 17640 kb/s
[Parsed_channelmap_0 @ 0x55b60492bf80] Error parsing channel layout: 'unknown'.
[AVFilterGraph @ 0x55b604916d00] Error initializing filter 'channelmap' with args 'map=0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16:channel_layout=unknown'
Error initializing complex filters.
Invalid argument
 

Я также пробовал такие значения, как any , all none , 0x0 и 0xFF с тем же результатом.
Я пытался использовать mono (поскольку каналы вроде как независимы), но ffmpeg пытается быть умным и говорит мне, что в моно-макете не должно быть 17 каналов.

Я знаю, что ffmpeg могу обрабатывать многоканальные файлы без макета. Например. преобразование 25-канального файла без -filter_complex "..." работ без проблем и ffprobe дает мне макет unknown канала.

Итак: как мне сказать ffmpeg , чтобы просто не обращать внимания на channel_layout при создании выходного файла, который содержит только подмножество входных каналов?

Комментарии:

1. Будет ли работать «произвольный макет» на входящих каналах? trac.ffmpeg.org/wiki /…

2. я не уверен, что понимаю предложение; У меня нет контроля над входными файлами (но я мог бы запустить их через ffmpeg на этапе предварительной обработки).

3. Я имею в виду, что вместо того, чтобы пытаться пометить макет «неизвестным», вы вместо этого помечаете его произвольным макетом, чтобы удовлетворить его.

4. я думаю, это было бы хорошо (хорошим макетом кандидата может быть «mono mono mono …»). я не совсем понимаю, как это сделать….

5. хм, я пробовал что-то вроде -filter_complex "pan=17c|c0=c0|c1=c1|c2=c2|c3=c3|c4=c4|c5=c5|c6=c6|c7=c7|c8=c8|c9=c9|c10=c10|c11=c11|c12=c12|c13=c13|c14=c14|c15=c15|c16=c16[a]" -map "[a]" , но это также не удается из-за «Недопустимого расположения каналов» (он работает только с 16 каналами)

Ответ №1:

Основываясь на манипуляциях с аудиоканалами, вы можете попробовать разделить их на n отдельные потоки amerge и объединить их вместе:

 -filter_complex "
[0:a]pan=mono|c0=c0[a0];
[0:a]pan=mono|c0=c1[a1];
[0:a]pan=mono|c0=c2[a2];
[0:a]pan=mono|c0=c3[a3];
[0:a]pan=mono|c0=c4[a4];
[0:a]pan=mono|c0=c5[a5];
[0:a]pan=mono|c0=c6[a6];
[0:a]pan=mono|c0=c7[a7];
[0:a]pan=mono|c0=c8[a8];
[0:a]pan=mono|c0=c9[a9];
[0:a]pan=mono|c0=c10[a10];
[0:a]pan=mono|c0=c11[a11];
[0:a]pan=mono|c0=c12[a12];
[0:a]pan=mono|c0=c13[a13];
[0:a]pan=mono|c0=c14[a14];
[0:a]pan=mono|c0=c15[a15];
[0:a]pan=mono|c0=c16[a16];
[a0][a1][a2][a3][a4][a5][a6][a7][a8][a9][a10][a11][a12][a13][a14][a15][a16]amerge=inputs=17"
 

Комментарии:

1. круто, что, кажется, работает. фактический фильтр, который я использую, это "$(seq -s';' -f '[0:a]pan=mono|c%g' 0 $((channels-1)) | sed -e 's|c([0-9]*)|c0=c1[a1]|g');$(seq -f "[a%g]" -s "" 0 $((channels-1)))amerge=inputs=${channels}"

2. Спасибо @aergistal за ввод. Мне пришлось изменить его, потому что в [0:a] был только c0, поэтому я не мог использовать c1, c2 и так далее. Хитрость заключалась в том, чтобы использовать [0: a: 0] [0: a: 1] и так далее, и pan = mono = c0 для каждого канала.

Ответ №2:

Основываясь на ответе от @aergistal и работая с файлом mxf с 10 аудиопотоками, мне пришлось изменить фильтр, чтобы указать входные данные для каждого панорамного фильтра. При работе с «pan = mono» используется только один канал, идентифицированный как c0

 -filter_complex "
[0:a:0]pan=mono|c0=c0[a0];
[0:a:1]pan=mono|c0=c0[a1];
[0:a:2]pan=mono|c0=c0[a2];
[0:a:3]pan=mono|c0=c0[a3];
[0:a:4]pan=mono|c0=c0[a4];
[0:a:5]pan=mono|c0=c0[a5];
[0:a:6]pan=mono|c0=c0[a6];
[0:a:7]pan=mono|c0=c0[a7];
[0:a:8]pan=mono|c0=c0[a8];
[0:a:9]pan=mono|c0=c0[a9];
[a0][a1][a2][a3][a4][a5][a6][a7][a8][a9]amerge=inputs=10"