#python #streaming #named-pipes #blocking #popen
#питон #потоковое вещание #именованные каналы #блокировка #попен
Вопрос:
У меня есть процесс захвата, который записывает необработанные видеоданные и аудиоданные в файлы. Что-то вроде этого захватит 100 кадров данных.
./capture -n 100 -f video_file -a audio_file
Давая мне аудиофайл размером 768000 байт и видеофайл размером 414720000 байт. Похоже, они складываются, как и ожидалось:
- 414720000 == 1920×1080 (пикселей / кадр) * 2 (байт / пиксель) * 100 (кадров)
- 768000 == 48 кб (Гц) * 2 (байт / сэмпл) * 2 канала * 100 (кадров) / 25 (кадров / с)
Затем, когда я кодирую эти данные, например
ffmpeg -i audio_file -i video_file out.flv
Я получаю воспроизводимое видео со звуком (на самом деле у меня есть намного больше информации в командной строке, но это важные части для целей этого вопроса)
Теперь, я на самом деле хочу прямую трансляцию, а не файл, и я могу сделать это нормально только для видео с чем-то вроде этого:
./capture -f /dev/stdout | ffmpeg -i - udp://127.0.0.1:10000
Я получаю видеопоток без трансляции звука по udp, и я смог нормально принимать и воспроизводить поток. Но когда я хочу добавить звук в картинку, у меня возникают некоторые проблемы.. Я думаю, что я не могу отправить их обоих stdout
, и я не могу использовать stderr
, потому что процесс захвата уже обсуждает это. Поэтому я попытался сделать это с именованными каналами следующим образом:
mkfifo audio_pipe
mkfifo video_pipe
ffmpeg -i audio_pipe -i video_pipe out.flv amp;
./capture -f video_pipe -a audio_pipe
Но это не работает, кажется, все заходит в тупик. Я протестировал просто запуск ./capture -f video_file -a audio_file
, а затем открытие двух новых оболочек и выполнение cat video_file > /dev/null
и cat audio_file > /dev/null
, как только обе кошки будут запущены, это разблокирует процесс захвата, так что, похоже, у него нет проблем с записью в каналы. Я заглянул в источник кода захвата, и то, как он работает, связано с обратным вызовом «прибыл кадр» из более глубокого API, который затем переходит и записывает видеокадр и аудиоданные в таком порядке (он блокируется). Я не знаю, что делает ffmpeg, читает ли он входной видеофайл или аудиофайл последовательно, в любом порядке, или читает их одновременно в потоках. Я попытался изменить порядок на ffmpeg -i video_pipe -i audio_pipe out.flv
, но, к сожалению, все по-прежнему блокируется. Использование только одного именованного канала для видеоданных работает нормально.
Как я могу решить свою проблему? Я напишу его с помощью модуля подпроцесса python, как только пойму, как лучше всего избежать проблемы блокировки.
Комментарии:
1. Я считаю, что это ограничение в ffmpeg. Он не использует неблокирующий режим для чтения из FIFOs.
Ответ №1:
В Linux буфер канала ограничен 65 КБ, возможно, вы попадаете в тупик, когда capture не будет записывать больше звука, пока не сможет записать больше видео, а ffmpeg не будет читать больше видео, пока не получит больше звука.
Комментарии:
1. Я знаю об этом, я ищу обычный способ разрешения таких взаимоблокировок. Я бы предпочел не обрабатывать связь между захватом и кодировщиком вручную, если этого можно легко избежать.
Ответ №2:
В конце концов, я не смог заставить ffmpeg читать без блокировки из FIFOs, поэтому исходный код приложения capture был изменен для записи аудиокадров и видеокадров из отдельных рабочих потоков, а не последовательно.