Получите результат ffmpeg и передайте его скрипту python

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

В моей локальной сети постоянно транслируется Raspberry Pi, и я использую этот скрипт ffmpeg для сохранения видео внутри Pi.

ffmpeg -i http://0.0.0.0:8080/stream/video.mjpeg -vcodec copy -map 0 -f segment -segment_time 5 -segment_format mp4 capture-%05d.mp4

Скрипт довольно прост, он загружает и сохраняет 5 секунд видео непрерывно в локальном каталоге.

Получите результат ffmpeg и передайте его скрипту python

Вот что я пытаюсь сделать в конечном итоге

Upload all saved videos to a Cloud Storage, then delete the local copy

Я попытался передать вывод ffmpeg в сценарий Python, подобный этому, но он не работает так, как я себе представляю.

ffmpeg -i http://0.0.0.0:8080/stream/video.mjpeg -vcodec copy -map 0 -f segment -segment_time 5 -segment_format mp4 capture-%05d.mp4 | py test.py -p capture-%05d.mp4

Это мой сценарий, чтобы получить имя / путь к видео

import argparse

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-p', '--videoPath', type=str, help = "Path to recorded video", required=True)
    args = parser.parse_args()

    print(args.videoPath)

Вы хотите вывод команды ffmpeg в виде строки на Python?

Jay 01.05.2018 15:00

Я предпочитаю вывод в виде строки (имени файла). Например, capture-00001.mp4.

Rex Low 01.05.2018 15:01

Итак, в основном вы хотите скопировать вновь созданные файлы в облачное хранилище? Один из способов - запустить ffmpeg как отдельный процесс, а затем использовать модуль inotify в Python, чтобы узнать, когда новый файл полностью записан на диск.

Jay 01.05.2018 15:05

Другой способ - вызвать команду ffmpeg из питона, затем захватить ее стандартный вывод, а затем обработать этот вывод почти в реальном времени, а затем получить из него необходимые данные.

Jay 01.05.2018 15:07
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
802
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я просматривал справочную страницу ffmpeg и наткнулся на опцию loglevel.

-loglevel [repeat+]loglevel | -v [repeat+]loglevel
       Set the logging level used by the library.  Adding "repeat+" indicates that repeated log output should not be compressed to the first line and the "Last message repeated n
       times" line will be omitted. "repeat" can also be used alone.  If "repeat" is used alone, and with no prior loglevel set, the default loglevel will be used. If multiple
       loglevel parameters are given, using 'repeat' will not change the loglevel.  loglevel is a string or a number containing one of the following values:

       verbose, 40
           Same as "info", except more verbose.

Итак, вот простой однострочный обходной путь, чтобы заставить все работать в вашем случае:

ffmpeg -i my_vid_feed -vcodec copy -map 0 -f segment -segment_time 5 -loglevel 40 -segment_format mp4 capture-%05d.mp4 2>&1 | grep --line-buffered -Eo "segment:.+ended" | awk -F "'" '{print $2; system("")}' | xargs -n1 python my_processor.py -p

Я просто разбираю вывод ffmpeg, когда новый файл записывается полностью, подробный журнал выдает такую ​​строку:

[segment @ 0x7fc253817000] segment:'capture-00002.mp4' count:2 ended

Итак, я просто беру имя файла из строки и передаю его этому файлу python argparse. Параметр -n1 в xargs указывает ему передавать только один аргумент за раз в файл python, а затем выполнять сценарий python с этим файлом в качестве аргумента. Вот результат работы команды -

root$ ffmpeg -i my_vid_feed -vcodec copy -map 0 -f segment -segment_time 5 -loglevel 40 -segment_format mp4 capture-%05d.mp4 2>&1 | grep --line-buffered -Eo "segment:.+ended" | awk -F "'" '{print $2; system("")}' | xargs -n1 python my_processor.py -p
started
capture-00000.mp4
ended
started
capture-00001.mp4
ended
started
capture-00002.mp4
ended
started
capture-00003.mp4
ended

Используемый файл python - my_processor.py

import argparse
import time

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-p', '--videoPath', type=str, help = "Path to recorded video", required=True)
    args = parser.parse_args()
    print("started")
    print(args.videoPath)
    time.sleep(3)
    print("ended")

Единственный возможный недостаток этого будет заключаться в том, что в то время, когда будет запущен только один экземпляр python, и ваши задания будут выполняться последовательно после того, как будет выполнено предыдущее задание. Если вы хотите запускать их параллельно, вы тоже можете это сделать.

Превосходство! Вы точно поняли мои сомнения! Оцените усилия, но когда я пытаюсь запустить эти параметры, видео сохраняются, но xargs, похоже, не работает. Я наблюдал за процессами и увидел, что xargs и python работают, но вывода просто нет

Rex Low 01.05.2018 16:29

ах, это должна быть буферизация awk и ожидание полного заполнения буфера перед выполнением. Можно просто awk на awk -F "'" '{print $2; system("")}' сменить? Это должно сработать.

Jay 01.05.2018 16:36

Он по-прежнему ничего не печатает. Вот моя последняя команда. ffmpeg -i http://0.0.0.0:8080/stream/video.mjpeg -vcodec copy -map 0 -f segment -segment_time 5 -loglevel 40 -segment_format mp4 capture-%05d.mp4 2>&1 | grep --line-buffered -Eo "segment:.+ended" | awk -F "'" '{print $2; system("")}' | xargs -n1 python3.6 test.py -p

Rex Low 01.05.2018 17:09

ох, можешь ли ты попробовать это и посмотреть, получаешь ли ты какой-нибудь выход ffmpeg -i http://0.0.0.0:8080/stream/video.mjpeg -vcodec copy -map 0 -f segment -segment_time 5 -loglevel 40 -segment_format mp4 capture-%05d.mp4 2>&1 | grep --line-buffered -Eo "segment:.+ended"

Jay 01.05.2018 17:15

У меня есть возможность получить segment:'capture-00000.mp4' count:0 ended, и последующие кадры

Rex Low 01.05.2018 17:16

Вы также можете получить только имена файлов после добавления части awk в указанную выше команду?

Jay 01.05.2018 17:17

К сожалению, нет, даже с обоими вашими предложениями awk :(

Rex Low 01.05.2018 17:18

Вывод $ ffmpeg -i my_vid_feed -vcodec copy -map 0 -f segment -segment_time 5 -loglevel 40 -segment_format mp4 capture-%05d.mp4 2>&1 | grep --line-buffered -Eo "segment:.+ended" | awk -F "'" '{print $2; system("")}' - capture-00000.mp4 capture-00001.mp4 capture-00002.mp4 Я могу видеть имена файлов в реальном времени, хотя по мере того, как они продолжают поступать, и они не буферизуются для меня. На какой платформе вы находитесь?

Jay 01.05.2018 17:23

Я использую это на Raspberry Pi 3 Model B. armv7l. Распбиан GNU / Linux 8

Rex Low 01.05.2018 17:24

Можете проверить версию awk? Я предполагаю, что версия awk для Pi 3 очень старая, можете ли вы попробовать gawk вместо этого или обновить awk до более новой версии.

Jay 01.05.2018 17:27

Спасибо! Проблема была в awk! Я установил gawk и теперь вижу имена файлов!

Rex Low 01.05.2018 17:35

np, поэтому теперь весь конвейер, включая часть Python, должен начать работать, как задумано.

Jay 01.05.2018 17:40

Да, в самом деле! Теперь мне нужно будет найти способ загрузить видео в свое облачное хранилище. И я жду недостатка, о котором вы упомянули в ответе. Я думаю, что этот метод потенциально может раздуть мой Pi до смерти, потому что по сути он пытается вызвать новый экземпляр python каждый раз, когда сохраняет видео. У вас есть лучший способ подойти к этому?

Rex Low 01.05.2018 17:43

Да, но в данный момент одновременно может выполняться только один процесс Python. Другой вариант - запустить процесс ffmpeg из самого python, а затем обработать его вывод на python и затем загрузить их в облако. Но тогда вам придется управлять множеством крайних случаев и одновременным / асинхронным / тайм-аутом для загрузки. Другим вариантом может быть inotify в сочетании с многопроцессорностью. inotify - это, по сути, системная ловушка, которая сообщает вам, создаются ли новые файлы в данном каталоге, а затем обрабатывает эти вновь созданные файлы параллельно, если вы хотите.

Jay 01.05.2018 17:52

Я попробовал первый вариант. Мне удалось создать несколько потоков для одновременной обработки всех запросов. Но наступает время, когда процессы ограничиваются вводом-выводом и сетевым трафиком, поэтому мои последние алгоритмы сильно задерживаются. Попробую второй подход.

Rex Low 01.05.2018 18:10

Да, параллелизм всегда должен быть ограничен и управляем в подходах. Вы можете сделать это любым подходом. Как и в первом подходе, 3-4 параллельных потока должны быть в порядке (вы можете провести несколько тестов и решить, что лучше всего подходит для вас с точки зрения ввода-вывода и использования ресурсов). Кроме того, вы, вероятно, также можете добавить несколько тайм-аутов / повторных попыток в случае сбоя запроса, чтобы сделать утилиту более надежной.

Jay 01.05.2018 18:16

Собственно мои мысли. Спасибо за ваш ответ на мои сомнения.

Rex Low 01.05.2018 18:16

нп, рад помочь! :)

Jay 01.05.2018 18:18

Другие вопросы по теме