Gwe*_*n J 1 python video ffmpeg transcoding
我的问题基于https://github.com/kkroening/ffmpeg-python/blob/master/examples/show_progress.py 理想情况下,我想要的只是跟踪转码过程,例如 0 - 100,发出流媒体产量对我的 gRPC 客户端的响应。从技术上讲,我不需要进度条。如何向 ffmpeg 子进程提供自己的套接字并处理对其的写入事件?
您可以将“进度”重定向到stdout使用-progress pipe:1.
请参阅如何将 ffmpeg 的 -progress 选项输出重定向到 stderr?
困难的部分是实际获得百分比进度。
-progress到stdout.stdout。frame=xx,获取框架,并将其放入列表(1 个元素的列表)中。该代码首先构建一个合成视频文件input.mp4- 用作输入。
这是一个“自包含”代码示例:
import subprocess as sp
import shlex
import json
from threading import Thread
import time
def progress_reader(procs, q):
while True:
if procs.poll() is not None:
break # Break if FFmpeg sun-process is closed
progress_text = procs.stdout.readline() # Read line from the pipe
# Break the loop if progress_text is None (when pipe is closed).
if progress_text is None:
break
progress_text = progress_text.decode("utf-8") # Convert bytes array to strings
# Look for "frame=xx"
if progress_text.startswith("frame="):
frame = int(progress_text.partition('=')[-1]) # Get the frame number
q[0] = frame # Store the last sample
# Build synthetic video for testing:
################################################################################
sp.run(shlex.split('ffmpeg -y -f lavfi -i testsrc=size=320x240:rate=30 -f lavfi -i sine=frequency=400 -f lavfi -i sine=frequency=1000 -filter_complex amerge -vcodec libx265 -crf 17 -pix_fmt yuv420p -acodec aac -ar 22050 -t 30 input.mp4'))
################################################################################
# Use FFprobe for counting the total number of frames
################################################################################
# Execute ffprobe (to show streams), and get the output in JSON format
# Actually counts packets instead of frames but it is much faster
# /sf/ask/141249041/#28376817
data = sp.run(shlex.split('ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 -of json input.mp4'), stdout=sp.PIPE).stdout
dict = json.loads(data) # Convert data from JSON string to dictionary
tot_n_frames = float(dict['streams'][0]['nb_read_packets']) # Get the total number of frames.
################################################################################
# Execute FFmpeg as sub-process with stdout as a pipe
# Redirect progress to stdout using -progress pipe:1 arguments
process = sp.Popen(shlex.split('ffmpeg -y -loglevel error -i input.mp4 -acodec libvorbis -vcodec libvpx-vp9 -crf 20 -pix_fmt yuv420p -progress pipe:1 output.webm'), stdout=sp.PIPE)
q = [0] # We don't really need to use a Queue - use a list of of size 1
progress_reader_thread = Thread(target=progress_reader, args=(process, q)) # Initialize progress reader thread
progress_reader_thread.start() # Start the thread
while True:
if process.poll() is not None:
break # Break if FFmpeg sun-process is closed
time.sleep(1) # Sleep 1 second (do some work...)
n_frame = q[0] # Read last element from progress_reader - current encoded frame
progress_percent = (n_frame/tot_n_frames)*100 # Convert to percentage.
print(f'Progress [%]: {progress_percent:.2f}') # Print the progress
process.stdout.close() # Close stdin pipe.
progress_reader_thread.join() # Join thread
process.wait() # Wait for FFmpeg sub-process to finish
Run Code Online (Sandbox Code Playgroud)
笔记:
ffmpeg和ffprobe位于可执行路径中。示例输出:
import subprocess as sp
import shlex
import json
from threading import Thread
import time
def progress_reader(procs, q):
while True:
if procs.poll() is not None:
break # Break if FFmpeg sun-process is closed
progress_text = procs.stdout.readline() # Read line from the pipe
# Break the loop if progress_text is None (when pipe is closed).
if progress_text is None:
break
progress_text = progress_text.decode("utf-8") # Convert bytes array to strings
# Look for "frame=xx"
if progress_text.startswith("frame="):
frame = int(progress_text.partition('=')[-1]) # Get the frame number
q[0] = frame # Store the last sample
# Build synthetic video for testing:
################################################################################
sp.run(shlex.split('ffmpeg -y -f lavfi -i testsrc=size=320x240:rate=30 -f lavfi -i sine=frequency=400 -f lavfi -i sine=frequency=1000 -filter_complex amerge -vcodec libx265 -crf 17 -pix_fmt yuv420p -acodec aac -ar 22050 -t 30 input.mp4'))
################################################################################
# Use FFprobe for counting the total number of frames
################################################################################
# Execute ffprobe (to show streams), and get the output in JSON format
# Actually counts packets instead of frames but it is much faster
# https://stackoverflow.com/questions/2017843/fetch-frame-count-with-ffmpeg/28376817#28376817
data = sp.run(shlex.split('ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 -of json input.mp4'), stdout=sp.PIPE).stdout
dict = json.loads(data) # Convert data from JSON string to dictionary
tot_n_frames = float(dict['streams'][0]['nb_read_packets']) # Get the total number of frames.
################################################################################
# Execute FFmpeg as sub-process with stdout as a pipe
# Redirect progress to stdout using -progress pipe:1 arguments
process = sp.Popen(shlex.split('ffmpeg -y -loglevel error -i input.mp4 -acodec libvorbis -vcodec libvpx-vp9 -crf 20 -pix_fmt yuv420p -progress pipe:1 output.webm'), stdout=sp.PIPE)
q = [0] # We don't really need to use a Queue - use a list of of size 1
progress_reader_thread = Thread(target=progress_reader, args=(process, q)) # Initialize progress reader thread
progress_reader_thread.start() # Start the thread
while True:
if process.poll() is not None:
break # Break if FFmpeg sun-process is closed
time.sleep(1) # Sleep 1 second (do some work...)
n_frame = q[0] # Read last element from progress_reader - current encoded frame
progress_percent = (n_frame/tot_n_frames)*100 # Convert to percentage.
print(f'Progress [%]: {progress_percent:.2f}') # Print the progress
process.stdout.close() # Close stdin pipe.
progress_reader_thread.join() # Join thread
process.wait() # Wait for FFmpeg sub-process to finish
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2079 次 |
| 最近记录: |