Hi,I tried use gstreamer command run
realtime gmsl video and 1 minute save video at same time,
Use theese code at command line is work:
gst-launch-1.0 \
nvstreammux width=1920 height=1080 batch-size=1 name=mux ! \
nvmultistreamtiler rows=2 columns=2 width=1920 height=1080 name=tiler ! \
nvvideoconvert ! \
tee name=t ! \
queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! \
nveglglessink sync=false \
t. ! \
queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! \
x264enc bitrate=5000 tune=zerolatency ! \
splitmuxsink location="output_video_$(date +%Y%m%d_%H%M%S)_%09d.mp4" max-size-time=60000000000 \
v4l2src device=/dev/video0 ! \
nvvideoconvert ! mux.sink_0 \
v4l2src device=/dev/video1 ! \
nvvideoconvert ! mux.sink_1 \
v4l2src device=/dev/video2 ! \
nvvideoconvert ! mux.sink_2 \
v4l2src device=/dev/video3 ! \
nvvideoconvert ! mux.sink_3
But can’t update date time,
So I tried use python GObject Introspection:
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GLib
import time
from datetime import datetime, timedelta
import sys
import signal
class GstreamerRecorder:
def __init__(self):
Gst.init(None)
self.mainloop = GLib.MainLoop()
self.increment = 60 # 秒
self.index = 0
self.initial_time = 0
self.pipeline = None
def create_pipeline(self, filename):
# 創建 pipeline
self.pipeline = Gst.Pipeline.new('video-pipeline')
# 創建元素
streammux = Gst.ElementFactory.make('nvstreammux', 'mux')
tiler = Gst.ElementFactory.make('nvmultistreamtiler', 'tiler')
converter = Gst.ElementFactory.make('nvvideoconvert', 'converter')
tee = Gst.ElementFactory.make('tee', 'tee')
queue1 = Gst.ElementFactory.make('queue', 'queue1')
queue2 = Gst.ElementFactory.make('queue', 'queue2')
sink = Gst.ElementFactory.make('nveglglessink', 'sink')
encoder = Gst.ElementFactory.make('x264enc', 'encoder')
filesink = Gst.ElementFactory.make('splitmuxsink', 'filesink')
# 創建源和轉換器
sources = []
converters = []
for i in range(4):
src = Gst.ElementFactory.make('v4l2src', f'src{i}')
conv = Gst.ElementFactory.make('nvvideoconvert', f'conv{i}')
src.set_property('device', f'/dev/video{i}')
sources.append(src)
converters.append(conv)
# 設置元素屬性
streammux.set_property('width', 1920)
streammux.set_property('height', 1080)
streammux.set_property('batch-size', 1)
tiler.set_property('rows', 2)
tiler.set_property('columns', 2)
tiler.set_property('width', 1920)
tiler.set_property('height', 1080)
queue1.set_property('max-size-buffers', 0)
queue1.set_property('max-size-time', 0)
queue1.set_property('max-size-bytes', 0)
queue2.set_property('max-size-buffers', 0)
queue2.set_property('max-size-time', 0)
queue2.set_property('max-size-bytes', 0)
sink.set_property('sync', False)
encoder.set_property('bitrate', 5000)
encoder.set_property('key-int-max', 30) # 每秒一個關鍵幀
encoder.set_property('bframes', 0) # 禁用 B 幀以提高相容性
encoder.set_property('tune', 'zerolatency') # 降低延遲
filesink.set_property('location', filename)
filesink.set_property('max-size-time', 60000000000)
# 添加元素到 pipeline
elements = [streammux, tiler, converter, tee, queue1, queue2,
sink, encoder, filesink] + sources + converters
for element in elements:
self.pipeline.add(element)
# 連接元素
# 連接源到轉換器,再到 streammux
for i in range(4):
sources[i].link(converters[i])
sink_pad = streammux.get_request_pad(f'sink_{i}')
src_pad = converters[i].get_static_pad('src')
src_pad.link(sink_pad)
# 連接主要 pipeline
streammux.link(tiler)
tiler.link(converter)
converter.link(tee)
# 連接 tee 的第一個分支到顯示
tee_video_pad = tee.get_request_pad('src_0')
queue1_pad = queue1.get_static_pad('sink')
tee_video_pad.link(queue1_pad)
queue1.link(sink)
# 連接 tee 的第二個分支到檔案
tee_file_pad = tee.get_request_pad('src_1')
queue2_pad = queue2.get_static_pad('sink')
tee_file_pad.link(queue2_pad)
queue2.link(encoder)
encoder.link(filesink)
return self.pipeline
def on_bus_message(self, bus, message, loop):
t = message.type
if t == Gst.MessageType.EOS:
print("Pipeline 結束")
loop.quit()
elif t == Gst.MessageType.ERROR:
err, debug = message.parse_error()
print(f"Error: {err}, {debug}")
loop.quit()
return True
def start_recording(self):
try:
while True:
# 計算下一個檔案的時間戳
next_time = datetime.now() + timedelta(seconds=self.initial_time)
timestamp = next_time.strftime("%Y%m%d_%H%M%S")
filename = f"output_video_{timestamp}_{self.index}.mp4"
print(f"開始錄製: {filename}")
# 創建新的 pipeline
if self.pipeline:
self.pipeline.set_state(Gst.State.NULL)
self.pipeline = self.create_pipeline(filename)
# 設置 bus 監聽
bus = self.pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message', self.on_bus_message, self.mainloop)
# 啟動 pipeline
self.pipeline.set_state(Gst.State.PLAYING)
# 等待指定時間
time.sleep(self.increment)
# 更新計數器和時間
self.initial_time += self.increment
self.index += 1
except KeyboardInterrupt:
print("\n程式停止")
if self.pipeline:
self.pipeline.set_state(Gst.State.NULL)
sys.exit(0)
def stop_recording(self, signum, frame):
print("\n接收到停止信號")
if self.pipeline:
self.pipeline.set_state(Gst.State.NULL)
sys.exit(0)
def main():
recorder = GstreamerRecorder()
# 註冊信號處理
signal.signal(signal.SIGINT, recorder.stop_recording)
signal.signal(signal.SIGTERM, recorder.stop_recording)
# 開始錄製
recorder.start_recording()
if __name__ == "__main__":
main()
The video really save to local and split 1 minute to file,
But can’t play on vlc or other media player,
How can I fix it?
Thanks!!!