一、流服務器搭建
1、安裝
sudo apt-get install software-properties-common python-software-properties
sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get install nginx
sudo apt-get install libnginx-mod-rtmp
2、配置文件修改
sudo gedit /etc/nginx/nginx.conf
添加:
rtmp {
servername {
listen 1935;
chunk_size 4096;
application live {
live on;
}
}
}
sudo service nginx restart
然後推出的流地址就可以是: rtmp://ip:1935/servername/name
二、opencv處理視頻流並推出
1、讀取流
和讀取攝像頭一樣,`cap = cv2.VideoCapture(rtmp_)`
可用的rtmp地址:
- rtmp://58.200.131.2:1935/livetv/hunantv 湖南衛視
- rtmp://202.69.69.180:443/webcast/bshdlive-pc 香港財經,很流暢!!!
注意: 抓取rtmp流可能一次抓不到,所以得多抓幾次,特別是自己搭的rtmp流更得多抓幾次!!
下面是測試rtmp的代碼,開始抓出錯繼續抓,抓到後中斷了又繼續抓。
rtmp = 'rtmp://192.168.1.18:1935/jiteng/3d'#'rtmp://58.200.131.2:1935/livetv/hunantv'#
# nginx 搭建的rtmp服務器,有時第一次抓不到,要多次抓取。
count_open_cap = 0
print ('開始抓取!')
cap = cv2.VideoCapture(rtmp)
while 1:
if cap.isOpened():
w,h,fps = int(cap.get(3)),int(cap.get(4)),cap.get(5)
print ('抓取成功!',w,h,fps)
count_open_cap = 0
break
else:
count_open_cap += 1
print ('嘗試抓取第'+str(count_open_cap+1)+'次!')
cap = cv2.VideoCapture(rtmp)
if count_open_cap == 4:
print ('嘗試抓取了5次,失敗!')
sys.exit()
break
continue
ret,img = cap.read()
if img is not None:
cv2.imwrite('live_test.jpg',img)
#cv2.namedWindow('live_test',2)
while 1:
ret,img = cap.read()
if ret == 0:
count_open_cap += 1
cap = cv2.VideoCapture(rtmp)
print ('中斷後,嘗試抓取第'+str(count_open_cap+1)+'次!')
if count_open_cap == 4:
print ('中斷後,嘗試抓取了5次,失敗!')
sys.exit()
break
continue
if count_open_cap != 0:
print ('抓取成功!')
count_open_cap = 0
cv2.imshow('live_3d',img)
if cv2.waitKey(int(1000/fps)) == 27:
break
cv2.destroyAllWindows()
cap.release()
2、處理流
同`ret,img = cap.read()`,然後直接一幀幀處理就好了
3、實時推出
參考文章
原理就是利用FFmpeg將幀進行轉碼推出,而幀通過subprocess的管道(pipe)進行提取,這樣結合就可以處理後實時轉碼推出了。
import subprocess as sp
#通過管道pipe來使用了ffmpeg提供的rtmp推流工具,init
def pipe_init(self):
# 直播管道輸出
# ffmpeg推送rtmp 重點 : 通過管道 共享數據的方式
command = ['ffmpeg',
'-y',
'-f', 'rawvideo',
'-vcodec','rawvideo',
'-pix_fmt', 'bgr24',
'-s', str(self.w)+ 'x' +str(self.h),
'-r', str(self.fps),
'-i', '-',
'-c:v 1', 'libx264',
'-pix_fmt', 'yuv420p',
'-preset', 'ultrafast',
'-f', 'flv',
self.out_rtmp]
#管道特性配置
pipe = sp.Popen(command, stdin=sp.PIPE) #,shell=False
return pipe
#將圖片推入管道中
def frame2pipe(self,pipe,frame):
# 結果幀處理 存入文件 / 推流 / ffmpeg 再處理
pipe.stdin.write(frame.tostring()) # 存入管道用於直播