问题
I have a python script that will produce frames for a video stream. To stream it to twitch I decided to use ffmpeg (as it is the only option I found). However, the bitrate of my stream is very low (70 KB), although in ffmpeg options it's set to 3000K.
# This script copies the video frame by frame
import cv2
import subprocess as sp
twitch_stream_key = 'MY_TWITCH_STREAM_KEY'
input_file = 'video.mp4'
cap = cv2.VideoCapture(input_file)
ret, frame = cap.read()
height, width, ch = frame.shape
ffmpeg = 'FFMPEG'
dimension = '{}x{}'.format(width, height)
fps = cap.get(cv2.CAP_PROP_FPS)
command = []
command.extend([
'FFMPEG',
'-loglevel', 'verbose',
'-y', # overwrite previous file/stream
'-analyzeduration', '1',
'-f', 'rawvideo',
'-r', '%d' % fps, # set a fixed frame rate
'-vcodec', 'rawvideo',
# size of one frame
'-s', '%dx%d' % (width, height),
'-pix_fmt', 'rgb24', # The input are raw bytes
'-thread_queue_size', '1024',
'-i', '-', # The input comes from a pipe
])
command.extend([
'-ar', '8000',
'-ac', '1',
'-f', 's16le',
'-i', 'work.mp3',
])
command.extend([
# VIDEO CODEC PARAMETERS
'-vcodec', 'libx264',
'-r', '%d' % fps,
'-b:v', '3000k',
'-s', '%dx%d' % (width, height),
'-preset', 'faster', '-tune', 'zerolatency',
'-crf', '23',
'-pix_fmt', 'yuv420p',
'-minrate', '3000k', '-maxrate', '3000k',
'-bufsize', '12000k',
'-g', '60', # key frame distance
'-keyint_min', '1',
# AUDIO CODEC PARAMETERS
'-acodec', 'libmp3lame', '-ar', '44100', '-b:a', '160k',
# '-bufsize', '8192k',
'-ac', '1',
'-map', '0:v', '-map', '1:a',
'-threads', '2',
# STREAM TO TWITCH
'-f', 'flv', 'rtmp://live-hel.twitch.tv/app/%s' %
twitch_stream_key
])
proc = sp.Popen(command, stdin=sp.PIPE, stderr=sp.PIPE)
while True:
ret, frame = cap.read()
if not ret:
break
proc.stdin.write(frame.tostring())
cap.release()
proc.stdin.close()
proc.stderr.close()
proc.wait()
How can I increase the bitrate? Maybe you can point me towards some different solution on how I can stream python frames to twitch or any other rtmp server.
Here is the complete log, the audio is also broken, it's just noise:
ffmpeg version git-2020-06-01-dd76226 Copyright (c) 2000-2020 the FFmpeg developers
built with gcc 9.3.1 (GCC) 20200523
configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libsrt --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --disable-w32threads --enable-libmfx --enable-ffnvcodec --enable-cuda-llvm --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt --enable-amf
libavutil 56. 49.100 / 56. 49.100
libavcodec 58. 90.100 / 58. 90.100
libavformat 58. 44.100 / 58. 44.100
libavdevice 58. 9.103 / 58. 9.103
libavfilter 7. 84.100 / 7. 84.100
libswscale 5. 6.101 / 5. 6.101
libswresample 3. 6.100 / 3. 6.100
libpostproc 55. 6.100 / 55. 6.100
Input #0, rawvideo, from 'pipe:':
Duration: N/A, start: 0.000000, bitrate: 1443225 kb/s
Stream #0:0: Video: rawvideo, 1 reference frame (RGB[24] / 0x18424752), rgb24, 1920x1080, 1443225 kb/s, 29 tbr, 29 tbn, 29 tbc
[s16le @ 0000026d64eb5340] Estimating duration from bitrate, this may be inaccurate
Guessed Channel Layout for Input Stream #1.0 : mono
Input #1, s16le, from 'work.mp3':
Metadata:
encoded_by : iTunes v7.0
Duration: 00:09:36.13, bitrate: 128 kb/s
Stream #1:0: Audio: pcm_s16le, 8000 Hz, mono, s16, 128 kb/s
[tcp @ 0000026d64ee34c0] Starting connection attempt to 99.181.64.78 port 1935
[tcp @ 0000026d64ee34c0] Successfully connected to 99.181.64.78 port 1935
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
Stream #1:0 -> #0:1 (pcm_s16le (native) -> mp3 (libmp3lame))
[graph 0 input from stream 0:0 @ 0000026d64f47c00] w:1920 h:1080 pixfmt:rgb24 tb:1/29 fr:29/1 sar:0/1
[scaler_out_0_0 @ 0000026d64f4c780] w:1920 h:1080 flags:'bicubic' interl:0
[scaler_out_0_0 @ 0000026d64f4c780] w:1920 h:1080 fmt:rgb24 sar:0/1 -> w:1920 h:1080 fmt:yuv420p sar:0/1 flags:0x4
[libx264 @ 0000026d64edf840] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 0000026d64edf840] profile High, level 4.0, 4:2:0, 8-bit
[libx264 @ 0000026d64edf840] 264 - core 160 - H.264/MPEG-4 AVC codec - Copyleft 2003-2020 - http://www.videolan.org/x264.html - options: cabac=1 ref=2 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=4 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=2 lookahead_threads=2 sliced_threads=1 slices=2 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=1 keyint=60 keyint_min=1 scenecut=40 intra_refresh=0 rc_lookahead=0 rc=crf mbtree=0 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 vbv_maxrate=3000 vbv_bufsize=12000 crf_max=0.0 nal_hrd=none filler=0 ip_ratio=1.40 aq=1:1.00
[graph_1_in_1_0 @ 0000026d651319c0] tb:1/8000 samplefmt:s16 samplerate:8000 chlayout:0x4
[format_out_0_1 @ 0000026d65132d80] auto-inserting filter 'auto_resampler_0' between the filter 'Parsed_anull_0' and the filter 'format_out_0_1'
[auto_resampler_0 @ 0000026d651331c0] ch:1 chl:mono fmt:s16 r:8000Hz -> ch:1 chl:mono fmt:s16p r:44100Hz
Output #0, flv, to 'rtmp://live-hel.twitch.tv/app/live_*************':
Metadata:
encoder : Lavf58.44.100
Stream #0:0: Video: h264 (libx264), 1 reference frame ([7][0][0][0] / 0x0007), yuv420p(progressive), 1920x1080, q=-1--1, 3000 kb/s, 29 fps, 1k tbn, 29 tbc
Metadata:
encoder : Lavc58.90.100 libx264
Side data:
cpb: bitrate max/min/avg: 3000000/0/3000000 buffer size: 12000000 vbv_delay: N/A
Stream #0:1: Audio: mp3 (libmp3lame) ([2][0][0][0] / 0x0002), 44100 Hz, mono, s16p, delay 1105, 160 kb/s
Metadata:
encoder : Lavc58.90.100 libmp3lame
回答1:
here is a minimum implementation to stream to twitch or other RTMP servers:
import threading, signal, os, sys, time, logging
import numpy as np
import cv2
import subprocess as sp
cap = cv2.VideoCapture(0)
frame_width= 1280
frame_height=720
FPS = 30
cap.set(cv2.CAP_PROP_FRAME_WIDTH, frame_width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, frame_height)
cap.set(cv2.CAP_PROP_FPS,FPS)
print("************ cv2.CAP_PROP_FPS : ", cap.get(cv2.CAP_PROP_FPS))
CBR='4500k'
command = [
'ffmpeg',
'-f', 'rawvideo',
'-vcodec','rawvideo',
'-s', str(frame_width)+'x'+str(frame_height),
'-pix_fmt', 'bgr24',
'-r', str(FPS),
'-i', '-',
'-stream_loop', '-1',
'-i', 'PATH_TO_YOUR_AUDIO_FILE.mp3',
'-f', 'flv',
'-vcodec', 'libx264',
'-profile:v', 'main',
'-g', '60',
'-keyint_min', '30',
'-b:v', CBR,
'-minrate', CBR,
'-maxrate', CBR,
'-pix_fmt', 'yuv420p',
'-preset', 'ultrafast',
'-tune', 'zerolatency',
'-threads', '0',
'-bufsize', CBR,
'rtmp://RTMP_SERVER_ULR/YOUR_CHANNEL_KEY']
proc = sp.Popen(command, stdin=sp.PIPE, stderr=sp.STDOUT, bufsize=0)
while True:
ret, frame = cap.read()
proc.stdin.write(frame.tostring())
cap.release()
proc.stdin.close()
proc.wait()
Few notes:
- opencv color pixel format is
bgr24notrgb24 - Youtube, Twitch, etc do not support adaptive bitrate, only constant bitrate
CBR, currently ffmpeg does not support constant bitrate out of the box so you need to set multiple parameters with the bitrate you want(b:v, minrate, maxrate, ) - Youtube require you to have audio in your stream
- Twitch latency is doubled if there is no audio in your stream
- in example above i m using a mp3 file in a loop but you can also use an audio source
- I suspect the reason you are not able to reach the bitrate you want is
-keyint_minis too low and-gtoo high, try setting-keyint_min=fpsand-g=fpsx2
回答2:
Original problem is due to using two conflicting modes of rate control. -b:v and -crf are mutually exclusive. Since you are streaming and want a more specific bitrate remove -crf.
来源:https://stackoverflow.com/questions/62156992/ffmpeg-streaming-to-twitch-low-bitrate