Выполнить команду ffmpeg из python с подпроцессом - PullRequest
0 голосов
/ 19 июня 2019

Следующая команда отлично работает из командной строки:

ffmpeg -y -threads 4 -i /dev/video0 -filter_complex "[v:0]scale=-2:720:force_original_aspect_ratio=decrease[vout001]" -c:v libx264 -b:v 2800k -maxrate:v 2996k -bufsize:v 4200k -c:a aac -b:a 128k -ac 2 -ar 48000 -preset veryfast -x264opts keyint=25:min-keyint=25:no-scenecut -sc_threshold 0 -r 25 -pix_fmt yuv420p -segment_list_flags +live -map [vout001] -f tee -var_stream_map 'v:0' "[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename='segment_%%06d_%Y%m%d%H%M%S.ts']playlist.m3u8|[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=\'http://X.X.X.X:pppp/ABCD/segment_%%06d_%Y%m%d%H%M%S.ts\':method=PUT]http://X.X.X.X:pppp/ABCD/playlist.m3u8"

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

cmd_ffmpeg = ['ffmpeg', '-y', '-threads', '4', '-i', '/dev/video0', '-filter_complex', '[v:0]scale=-2:720:force_original_aspect_ratio=decrease[vout001]', '-c:v', 'libx264', '-b:v', '2800k', '-maxrate:v', '2996k', '-bufsize:v', '4200k', '-c:a', 'aac', '-b:a', '128k', '-ac', '2', '-ar', '48000', '-preset', 'veryfast', '-x264opts', 'keyint=25:min-keyint=25:no-scenecut', '-sc_threshold', '0', '-r', '25', '-pix_fmt', 'yuv420p', '-segment_list_flags', '+live', '-map', '[vout001]', '-f', 'tee', '"[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=\'segment_%%06d_%Y%m%d%H%M%S.ts\']playlist.m3u8|[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=\'http://X.X.X.X:pppp/ABCD/segment_%%06d_%Y%m%d%H%M%S.ts\':method=PUT]http://X.X.X.X:pppp/ABCD/playlist.m3u8"']

Ошибка заключается в следующем:

No option found near "//X.X.X.X:pppp/ABCD/segment_%%06d_%Y%m%d%H%M%S.ts":method=PUT]http://X.X.X.X:pppp/ABCD/playlist.m3u8"

Он рассматривает ':' после 'http' как разделитель опций, когда он выполняется из кода Python (escape не работает), когда выполняется непосредственно изshell escape отлично работает.

Как мне решить эту проблему?

Ответы [ 4 ]

1 голос
/ 20 июня 2019

Спасибо, ребята, за ваши предложения и помощь. Я попробовал тройные кавычки, как это было предложено, но он создает другую проблему, состоящую из фрагментов видео / плейлиста со следующими именами файлов:

"f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=segment_%%06d_%Y%m%d%H%M%S.ts]playlist.m3u8

"f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=segment_%%06d_%Y%m0%H%M%S.ts]playlist0.ts

"f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=segment_%%06d_%Y%m11%H%M%S.ts]playlist11.ts

....

Итак, список параметров рассматривается как имя файла сегмента / списка воспроизведения. Кроме того, он генерирует один выход вместо двух выходов (один локально, а другой - на удаленный сервер).

На самом деле, решение состоит в том, чтобы сохранить ту же команду и добавить только «\» перед «:» в URL удаленного сервера. Итак, последняя команда, которая отлично работает из кода Python:

cmd_ffmpeg = ['ffmpeg', '-y', '-threads', '4', '-i', '/dev/video0', '-filter_complex', '[v:0]scale=-2:720:force_original_aspect_ratio=decrease[vout001]', '-c:v', 'libx264', '-b:v', '2800k', '-maxrate:v', '2996k', '-bufsize:v', '4200k', '-c:a', 'aac', '-b:a', '128k', '-ac', '2', '-ar', '48000', '-preset', 'veryfast', '-x264opts', 'keyint=25:min-keyint=25:no-scenecut', '-sc_threshold', '0', '-r', '25', '-pix_fmt', 'yuv420p', '-segment_list_flags', '+live', '-map', '[vout001]', '-f', 'tee', '-var_stream_map', 'v:0', '[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=\'segment_%%06d_%Y%m%d%H%M%S.ts\']playlist.m3u8|[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=\'http\\://X.X.X.X:pppp/ABCD/segment_%%06d_%Y%m%d%H%M%S.ts\']http://X.X.X.X:pppp/ABCD/playlist.m3u8']

Что касается параметра / значения: '-var_stream_map' и 'v: 0', я просто пропустил его. Это можно игнорировать, поскольку у нас есть один вход.

Спасибо.

1 голос
/ 19 июня 2019

Двойные кавычки вокруг длинной строки отбрасываются оболочкой до того, как ffmpeg увидит командную строку. Вы можете просто заменить их одинарными кавычками в Python. Наличие буквенных двойных кавычек внутри одинарных кавычек отбрасывает параметр синтаксического анализатора ffmpeg.

0 голосов
/ 21 июня 2019

Если вы хотите запустить команду ffmpeg в коде Python, вы можете попробовать это:

import os
cmd_ffmpeg = """ffmpeg -y -threads 4 -i /dev/video0 -filter_complex \"[v:0]scale=-2:720:force_original_aspect_ratio=decrease[vout001]\" -c:v libx264 -b:v 2800k -maxrate:v 2996k -bufsize:v 4200k -c:a aac -b:a 128k -ac 2 -ar 48000 -preset veryfast -x264opts keyint=25:min-keyint=25:no-scenecut -sc_threshold 0 -r 25 -pix_fmt yuv420p -segment_list_flags +live -map [vout001] -f tee -var_stream_map \'v:0\' \"[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=\'segment_%%06d_%Y%m%d%H%M%S.ts\']playlist.m3u8|[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=\'http://X.X.X.X:pppp/ABCD/segment_%%06d_%Y%m%d%H%M%S.ts\':method=PUT]http://X.X.X.X:pppp/ABCD/playlist.m3u8\""""
print(cmd_ffmpeg)
os.system(cmd_ffmpeg)
0 голосов
/ 19 июня 2019

Как вы сгенерировали cmd_ffmpeg ?Вручную?Это отличается от того, что возвращает shlex.split.Например, cmd_ffmpeg имеет двойные кавычки после filter_complex , тогда как то, что shlex.split не возвращает.

import shlex
shell_ffmpeg_cmd = r'''ffmpeg -y -threads 4 -i /dev/video0 -filter_complex "[v:0]scale=-2:720:force_original_aspect_ratio=decrease[vout001]" -c:v libx264 -b:v 2800k -maxrate:v 2996k -bufsize:v 4200k -c:a aac -b:a 128k -ac 2 -ar 48000 -preset veryfast -x264opts keyint=25:min-keyint=25:no-scenecut -sc_threshold 0 -r 25 -pix_fmt yuv420p -segment_list_flags +live -map [vout001] -f tee -var_stream_map 'v:0' "[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename='segment_%%06d_%Y%m%d%H%M%S.ts']playlist.m3u8|[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename=\'http://X.X.X.X:pppp/ABCD/segment_%%06d_%Y%m%d%H%M%S.ts\':method=PUT]http://X.X.X.X:pppp/ABCD/playlist.m3u8"'''
popen_args = shlex.split(shell_ffmpeg_cmd)
print(" ".join(popen_args))

Кроме того, эти два переключателя отсутствуют в cmd_ffmpeg по сравнению с вызовом вашей оболочки: -var_stream_map и 'v:0'.

Тем не менее, ваша проблема, кажется, с последним элементом в списке.Как подсказал eatmeimadanish, попробуйте трижды процитировать его.Ниже приведен ваш cmd_ffmpeg с последним исправленным элементом и тройной одинарной кавычкой.Он печатает stderr ffmpeg, который, по моему опыту, пригодится:

from subprocess import Popen, PIPE

cmd_ffmpeg = ['ffmpeg', '-y', '-threads', '4', '-i', '/dev/video0', '-filter_complex', '[v:0]scale=-2:720:force_original_aspect_ratio=decrease[vout001]', '-c:v', 'libx264', '-b:v', '2800k', '-maxrate:v', '2996k', '-bufsize:v', '4200k', '-c:a', 'aac', '-b:a', '128k', '-ac', '2', '-ar', '48000', '-preset', 'veryfast', '-x264opts', 'keyint=25:min-keyint=25:no-scenecut', '-sc_threshold', '0', '-r', '25', '-pix_fmt', 'yuv420p', '-segment_list_flags', '+live', '-map', '[vout001]', '-f', 'tee', '''"[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename='segment_%%06d_%Y%m%d%H%M%S.ts']playlist.m3u8|[f=hls:hls_time=1:hls_playlist_type=event:strftime=1:hls_flags=independent_segments+program_date_time+second_level_segment_index:hls_segment_filename='http://X.X.X.X:pppp/ABCD/segment_%%06d_%Y%m%d%H%M%S.ts':method=PUT]http://X.X.X.X:pppp/ABCD/playlist.m3u8"''']
with Popen(cmd_ffmpeg, text=True, stdout=PIPE, stderr=PIPE) as p:
    for line in p.stderr:
        print(line, end="") # stderr already includes a newline
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...