我试图使用streamlink将流作为单个帧处理。
args = ['streamlink', stream_url, "best", "-O"]
process = subprocess.Popen(args, stdout=subprocess.PIPE)
while True:
frame_size = width * height * 3
in_frame = streamlink.stdout.read(frame_size)
if in_frame is None:
break
#cv2.imwrite(f'frames/{i}.jpg', in_frame)
#do anything with in_frame
但是得到的图像看起来像白噪音。我认为这是因为流也包含以字节为单位的音频。然后,我尝试将其传输到ffmpeg,但无法从ffmpeg中获得解码字节。
args = (
ffmpeg.input('pipe:')
.filter('fps', fps=1)
.output('pipe:', vframes=1, format='image2', vcodec='mjpeg')
.compile()
)
process2 = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=None)
buff = process1.stdout.read(n)
process2.stdin.write(buff)
frame = process2.stdout.read(n)
当我尝试这样的smt时,我所有的脚本都挂着,等待着什么。如何正确处理流链接中的流作为单独的帧。以字节或其他方式获取帧?谢谢。
发布于 2021-10-08 21:00:53
与其将数据传递给FFmpeg,不如将URL作为输入参数传递给FFmpeg。
def stream_to_url(url,quality='best'):session = Streamlink() stream_to_url= session.streams(url)返回stream_to_url
P= ffmpeg.probe(stream_url,select_streams='v');宽度=p‘streams’宽度‘高度=ffmpeg.probe
process =( ffmpeg .input(stream_url) .video .output(管道:,格式=‘rawvideo’,pix_fmt='bgr24') .run_async(pipe_stdout=True) #以防ffmpeg在非可执行路径中,添加cmd=fullpath like:.run_async(pipe_stdout=True,cmd=r‘c:\FFmpeg\bin\ffmpeg.exe) )
..。in_bytes =process.stdout.read(宽*高* 3)帧= np.frombuffer(in_bytes,np.uint8).reshape(高,宽,3) cv2.imShow(帧,帧).
完整代码示例:
from streamlink import Streamlink
import numpy as np
import cv2
import ffmpeg
def stream_to_url(url, quality='best'):
""" Get URL, and return streamlink URL """
session = Streamlink()
streams = session.streams(url)
if streams:
return streams[quality].to_url()
else:
raise ValueError('Could not locate your stream.')
url = 'https://www.twitch.tv/riotgames' # Login to twitch TV before starting (the URL is for a random live stream).
quality='best'
stream_url = stream_to_url(url, quality)
# Use FFprobe to get video frames resolution (required in case resolution is unknown).
###############################################
p = ffmpeg.probe(stream_url, select_streams='v');
width = p['streams'][0]['width']
height = p['streams'][0]['height']
###############################################
# Execute FFmpeg sub-process with URL as input and raw (BGR) output format.
process = (
ffmpeg
.input(stream_url)
.video
.output('pipe:', format='rawvideo', pix_fmt='bgr24')
.run_async(pipe_stdout=True) # In case ffmpeg in not in executable path, add cmd=fullpath like: .run_async(pipe_stdout=True, cmd=r'c:\FFmpeg\bin\ffmpeg.exe')
)
# Read decoded video (frame by frame), and display each frame (using cv2.imshow)
while True:
# Read raw video frame from stdout as bytes array.
in_bytes = process.stdout.read(width * height * 3)
if not in_bytes:
break
# Transform the byte read into a NumPy array
frame = np.frombuffer(in_bytes, np.uint8).reshape([height, width, 3])
# Display the frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
process.stdout.close()
process.wait()
cv2.destroyAllWindows()
有一个使用cv2.VideoCapture
的更简单的解决方案
stream_url = stream_to_url(url, quality)
cap = cv2.VideoCapture(stream_url)
while True:
success, frame = cap.read()
if not success:
break
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
更新:
从Streamlink子进程到FFmpeg子进程的管道
假设您必须从Streamlink的stdout管道读取流,并将其写入FFmpeg的stdin管道:
-O
参数):streamlink_args = r'c:\Program (X86)\ Streamlink \bin\Strelin.exe‘,stream_url,“最佳”,"-O“# Windows可执行文件下载自:https://github.com/streamlink/streamlink/releases/tag/2.4.0 streamlink_process = sp.Popen(streamlink_args,stdout=sp.PIPE) # executable作为子进程
def编写器(streamlink_proc,ffmpeg_proc):chunk (非streamlink_proc.poll())和(not ffmpeg_proc.poll()):try: chunk= streamlink_proc.stdout.read(1024) ffmpeg_proc.stdin.write(区块) (BrokenPipeError,OSError)作为e: pass
ffmpeg_process =( ffmpeg .input(‘pix:’) .video .output(‘path:’,format='rawvideo',pix_fmt=‘bin 24’) .run_async(pipe_stdin=True,pipe_stdout=True) #以防ffmpeg在非可执行路径中,添加cmd=fullpath like:.run_async(pipe_stdout=True,cmd=r‘c:\FFmpeg\bin\ffmpeg.exe) )
thread.start() = threading.Thread(target=writer,args=(streamlink_process,ffmpeg_process))
完整代码示例:
import numpy as np
import subprocess as sp
import threading
import cv2
import ffmpeg
#stream_url = 'https://www.nimo.tv/v/v-1712291636586087045'
stream_url = 'https://www.twitch.tv/esl_csgo'
# Assume video resolution is known.
width, height = 1920, 1080
# Writer thread (read from streamlink and write to FFmpeg in chunks of 1024 bytes).
def writer(streamlink_proc, ffmpeg_proc):
while (not streamlink_proc.poll()) and (not ffmpeg_proc.poll()):
try:
chunk = streamlink_proc.stdout.read(1024)
ffmpeg_proc.stdin.write(chunk)
except (BrokenPipeError, OSError) as e:
pass
streamlink_args = [r'c:\Program Files (x86)\Streamlink\bin\streamlink.exe', stream_url, "best", "-O"] # Windows executable downloaded from: https://github.com/streamlink/streamlink/releases/tag/2.4.0
streamlink_process = sp.Popen(streamlink_args, stdout=sp.PIPE) # Execute streamlink as sub-process
# Execute FFmpeg sub-process with URL as input and raw (BGR) output format.
ffmpeg_process = (
ffmpeg
.input('pipe:')
.video
.output('pipe:', format='rawvideo', pix_fmt='bgr24')
.run_async(pipe_stdin=True, pipe_stdout=True) # In case ffmpeg in not in executable path, add cmd=fullpath like: .run_async(pipe_stdout=True, cmd=r'c:\FFmpeg\bin\ffmpeg.exe')
)
thread = threading.Thread(target=writer, args=(streamlink_process, ffmpeg_process))
thread.start()
# Read decoded video (frame by frame), and display each frame (using cv2.imshow)
while True:
# Read raw video frame from stdout as bytes array.
in_bytes = ffmpeg_process.stdout.read(width * height * 3)
if not in_bytes:
break
# Transform the byte read into a NumPy array
frame = np.frombuffer(in_bytes, np.uint8).reshape([height, width, 3])
# Display the frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
ffmpeg_process.stdout.close()
ffmpeg_process.wait()
#streamlink_process.stdin.close()
streamlink_process.kill()
cv2.destroyAllWindows()
备注:
代码示例使用指向twitch.tv的链接,而不是nimo.tv,因为"Nimo已损坏了流链接插件“。
https://stackoverflow.com/questions/69492115
复制相似问题