Python 與 FFmpeg

      在〈Python 與 FFmpeg〉中尚無留言

av

Windows : pip install av
Linux : sudo pip3 install av

av 調用ffmpeg 的sdk來執行的, 可以作更精細的動作. 只可惜的是, 並不支援硬体編碼. 而且官方也說了, 硬体編碼不在此專案的計畫當中, 看來只能死心了. 

存成圖片

底下代碼, 可以把影片裏的frame一幅一幅的存成 jpg圖片檔

ffmpeg指令 : ffmpeg -i ../snake.mkv -r 1 img-%5d.jpg
-r 1 : 每秒取一張. 數字可以自已變更

#!/usr/bin/python3
import av
container = av.open("../snake.mkv")
stream = container.streams.video[0]
stream.codec_context.skip_frame = 'NONKEY'

for frame in container.decode(stream):
    frame.to_image().save('f-%04d.jpg' % frame.pts)

轉換格式

import av
import av.datasets
input_ = av.open(path_to_video)
output = av.open('remuxed.mkv', 'w')
in_stream = input_.streams.video[0]
out_stream = output.add_stream(template=in_stream)
for packet in input_.demux(in_stream):
   if packet.dts is None:
       continue
   packet.stream = out_stream
   output.mux(packet)
output.close()

推播到rtmp

下面代碼, 可以自web cam取得影像, 解碼成 image後, 處理image, 然後再推播到rtmp. 只可惜 output_的編碼器若使用 h264_omx, 則整個會當掉. 此為PyAv的bug, 目前尚無解

所以只能用軟体編碼 “h264”, fps 只剩下 5fps. 所以目前放棄使用 PyAv

#!/usr/bin/python3
import av
import cv2
from datetime import datetime
input_ = av.open("/dev/video0")
in_stream=input_.streams.video[0]
in_stream.options={"input_format":"mjpeg", "video_size":"1920x1080"}
#in_stream.width=1920
#in_stream.height=1080

output_=av.open('rtmp://mahaljsp.asuscomm.com/live/car',mode='w', format='flv')

output_stream = output_.add_stream(codec_name="h264",rate=24)
output_stream.options = {"b":"4000k", "vcodec":"libx264", "video_size":"1920x1080"}

t1=datetime.now()
t2=t1
index=0
for frame in input_.decode(in_stream):
    for packet in output_stream.encode(frame):
        output_.mux(packet)
    t2=datetime.now()
    if (t2-t1).seconds>0:
       print(index)
       index=0
       t1=t2
    else:
        index+=1
    cv2.waitKey(5)
output_.close()

轉換成image再推播

此方式因要處理圖片, 所以要先 sudo pip3 install Pillow ttf-wqy-zenhei

#!/usr/bin/python3
import av
import time
import cv2
from PIL import ImageDraw
from PIL import ImageFont
from datetime import datetime
infile = av.open("/dev/video0")
instream=infile.streams.video[0]
instream.options={"input_format":"mjpeg", "video_size":"1920x1080"}

outfile=av.open('rtmp://mahaljsp.asuscomm.com/live/car',mode='w', format='flv')
outstream = outfile.add_stream(codec_name="h264",rate=24)
outstream.options = {"b":"4000k", "vcodec":"h264_omx", "video_size":"1920x1080", "threads":"16"}

t1=round(time.time() * 1000)
t2=t1
index=0

for packet in infile.demux():
    frame=packet.decode()[0]
    img = frame.to_image()
    datetime_dt = datetime.today()  # 獲得當地時間
    datetime_str = datetime_dt.strftime("%Y/%m/%d %H:%M:%S")  # 格式化日期
    draw = ImageDraw.Draw(img)
    draw.text((10,30), datetime_str, font=ImageFont.truetype("/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",36), fill=(0, 255, 255, 255))
    
    #底下這最編碼, 在樹莓派若採軟体編碼, 非常的慢, 頂多 2fps而以
    out_packet = outstream.encode(av.VideoFrame.from_image(img))
    outfile.mux(out_packet)
    t2=round(time.time() * 1000)
    if (t2-t1)>=1000:
       print(index)
       index=0
       t1=round(time.time() * 1000)
    else:
        index+=1

Windows 版

#!/usr/bin/python3
import av
import time
import cv2
from PIL import ImageDraw
from PIL import ImageFont
from datetime import datetime
#infile = av.open("/dev/video0")
infile = av.open("c922 Pro Stream Webcam", mode='r', format='vfwcap')
instream=infile.streams.video[0]
instream.options={"input_format":"mjpeg", "video_size":"1920x1080"}

outfile=av.open('rtmp://mahaljsp.asuscomm.com/live/car',mode='w', format='flv')
outstream = outfile.add_stream(codec_name="h264_nvenc",rate=24)
outstream.options = {"b":"4000k", "video_size":"1920x1080", "threads":"16"}

t1=round(time.time() * 1000)
t2=t1
index=0
for packet in infile.demux():
    frame=packet.decode()[0]
    img = frame.to_image()
    datetime_dt = datetime.today()  # 獲得當地時間
    datetime_str = datetime_dt.strftime("%Y/%m/%d %H:%M:%S")  # 格式化日期
    draw = ImageDraw.Draw(img)
    #draw.text((10,30), datetime_str, font=ImageFont.truetype("/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",36), fill=(0, 255, 255, 255))
    draw.text((10, 30), datetime_str, font=ImageFont.truetype("arial.ttf", 36),fill=(0, 255, 255, 255))


    #底下這最編碼, 在樹莓派若採軟体編碼, 非常的慢, 頂多 2fps而以
    out_packet = outstream.encode(av.VideoFrame.from_image(img))
    outfile.mux(out_packet)
    t2=round(time.time() * 1000)
    if (t2-t1)>=1000:
       print(index)
       index=0
       t1=round(time.time() * 1000)
    else:
        index+=1

ffmpy3

Windows : pip install ffmpy3
Linux : sudo pip3 install ffmpy3

ffmpy3好像是去執行ffmpeg這支程式的, 還不確定, 測試中

ffmpy3是在Python裏調用ffmpeg這支程式, 進行音視訊的操作, 記得將 ffmpeg這支程式放在專案裏

blog.csdn.net/qq_40962368/article/details/91355429

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *