Вопрос или проблема
Если я воспроизвожу аудио с командой ffmpeg -i test.flac -f alsa default
, терминал показывает такой вывод:
size=N/A time=00:00:21.31 bitrate=N/A speed=1.22x
Я хотел бы захватить параметр ‘time=”‘ и его значение. Я знаю, что ffmpeg выводит в STDERR, поэтому я знаю, что нужно перенаправить 2>1, поэтому я пытаюсь:
ffmpeg -i test.flac -f alsa default 2>&1 | grep time
…и терминал остается совершенно пустым в этот момент (хотя музыка играет вполне нормально).
Я также пробовал:
ffmpeg -i test.flac -f alsa default 2>test.txt
…и в сессии второго терминала:
tail -f test.txt | grep time
…и по-прежнему пусто, хотя если я просто использую tail без grep, я вижу соответствующую строку текста с постоянно увеличивающимся значением time=.
Я знаю, что будет предложено использовать ffplay, но я работаю с большим количеством кода, использующего ffmpeg, и переключение не является вариантом. На самом деле, меня больше интересует ответ на вопрос, почему grep просто не кажется работающим на выводе ffmpeg STDERR, независимо от того, куда он перенаправлен! Почти вторично: есть ли способ извлечь значение времени ‘текущей позиции в потоке’ используя только ffmpeg?
В свете комментариев ниже:
ffmpeg -v
ffmpeg version n7.1 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 14.2.1 (GCC) 20240910
И усеченный вывод от простого воспроизведения музыки, без перенаправлений:
TAGDATE : 1623718801
encoder : Lavf61.7.100
Stream #0:0: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s
Metadata:
encoder : Lavc61.19.100 pcm_s16le
size=N/A time=00:00:15.36 bitrate=N/A speed=1.34x
И некоторые примеры того, что я могу и не могу отфильтровать с помощью grep из этого вывода:
[zelenka Desktop]$ ffmpeg -i test.flac -f alsa default 2>&1 | grep Duration
Duration: 00:21:10.00, start: 0.000000, bitrate: 690 kb/s
^C^C^C
[zelenka Desktop]$ ffmpeg -i test.flac -f alsa default 2>&1 | grep Audio
Stream #0:0: Audio: flac, 44100 Hz, stereo, s16
Stream #0:0: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s
^C^C^C
[zelenka Desktop]$ ffmpeg -i test.flac -f alsa default 2>&1 | grep time=
^C^C^C
(И в этот момент мне нужно нажать Ctrl+C для прерывания, так как ничего не появляется на экране). Фильтрация ‘статических’ данных работает; фильтрация динамической части строки “size=N/A time=00:00:15.36 bitrate=N/A speed=1.34x” не срабатывает.
Ответ или решение
Чтобы извлечь параметр time=
из вывода FFmpeg при воспроизведении аудио, необходимо учитывать несколько важных аспектов, связанных с тем, как FFmpeg формирует свои выводы и как работают потоки данных в Unix-подобных операционных системах.
Понимание вывода FFmpeg
FFmpeg предоставляет информацию о процессе обработки медиафайлов через стандартный поток ошибок (STDERR). При этом динамические данные, такие как time=
, выводятся в реальном времени и могут быть непрерывно обновляемыми, что создает определенные сложности при их фильтрации с помощью оболочки.
Проблема с grep
и tail
Ваши наблюдения о том, что команда grep
не выводит строки с time=
скорее всего обусловлены тем, что FFmpeg периодически обновляет строку в терминале, а не генерирует новые строки. Таким образом, grep
не видит новых данных, так как они фактически не добавляются как новые строки — строка просто обновляется.
Решение через awk
или sed
Чтобы извлечь и отслеживать параметр time=
, вместо grep
стоит попробовать использовать awk
или sed
. Пример команды, которая будет фильтровать нужный вывод, может выглядеть следующим образом:
ffmpeg -i test.flac -f alsa default 2>&1 | awk '/time=/ {print $0}'
Или с использованием sed
:
ffmpeg -i test.flac -f alsa default 2>&1 | sed -n 's/.*time=\([^ ]*\).*/\1/p'
Либо для постоянного мониторинга времени в потоке можно использовать watch
с sed
:
ffmpeg -i test.flac -f alsa default 2>&1 | sed -u -n 's/.*time=\([^ ]*\).*/\1/p'
Извлечение времени через FFmpeg
Если вы хотите извлечь текущее время воспроизведения с помощью самого FFmpeg, у вас нет прямой команды для вывода этой информации в режиме реального времени. Однако, вы можете использовать функции FFmpeg для работы с API или скриптами, которые будут периодически запрашивать состоянии воспроизведения.
Использование библиотеки FFmpeg в рамках программирования позволяет получить информацию о текущем времени, используя внутренние данные и структуру данных, например, c помощью языка программирования Python и библиотеки ffmpeg-python
.
Заключение
Хотя grep
может быть полезным инструментом, в случае динамического вывода FFmpeg, использование awk
или sed
будет более эффективным способом получения интересующих данных. Это обеспечит более гибкий и надежный подход для извлечения времени воспроизведения и адаптации под ваши нужды.