tuoheng_alg_airport/test/ffmpeg_test.py

250 lines
10 KiB
Python
Raw Normal View History

2023-01-16 16:44:30 +08:00
# -*- coding: utf-8 -*-
import time
import cv2
import subprocess as sp
import ffmpeg
import numpy as np
from loguru import logger
'''
获取视频信息
'''
def get_video_info(pullUrl):
try:
probe = ffmpeg.probe(pullUrl)
if probe is None or probe.get("streams") is None:
return
# 视频大小
# format = probe['format']
# size = int(format['size'])/1024/1024
video_stream = next((stream for stream in probe['streams'] if stream.get('codec_type') == 'video'), None)
if video_stream is None:
logger.error("根据拉流地址未获取到视频流")
return
width = video_stream.get('width')
height = video_stream.get('height')
nb_frames = video_stream.get('nb_frames')
fps = video_stream.get('r_frame_rate')
# duration = video_stream.get('duration')
bit_rate = video_stream.get('bit_rate')
if width:
width = int(width)
if height:
height = int(height)
if nb_frames:
all_frames = int(nb_frames)
if fps:
up, down = str(fps).split('/')
fps = int(eval(up) / eval(down))
# if duration:
# self.duration = float(video_stream['duration'])
if bit_rate:
bit_rate = int(bit_rate) / 1000
logger.info("视频信息, width:{}|height:{}|fps:{}|all_frames:{}|bit_rate:{}", width,
height, fps, all_frames, bit_rate)
except ffmpeg._run.Error as er:
logger.error("获取视频信息异常: {}", er.stderr.decode(encoding='utf-8'))
except Exception as e:
logger.exception("获取视频信息异常:{}", e)
'''
拉取视频
'''
def build_pull_p(wh, pullUrl):
try:
command = [r'E:\liumeiti\ffmpeg\ffmpeg-master-latest-win64-gpl\bin\ffmpeg',
'-re',
'-y',
'-c:v', 'h264_cuvid',
'-resize', wh,
'-i', pullUrl,
'-f', 'rawvideo',
'-an',
'-']
return sp.Popen(command, stdout=sp.PIPE)
except Exception as e:
logger.exception("构建拉流管道异常:{}", e)
return None
def read(whr, whrz, pullUrl, h, w):
result = None
try:
in_bytes = build_pull_p(whrz, pullUrl).stdout.read(whr)
if in_bytes is not None and len(in_bytes) > 0:
# result = (np.frombuffer(in_bytes, np.uint8).reshape([int(self.height), int(self.width), 3]))
try:
img = (np.frombuffer(in_bytes, np.uint8)).reshape((h, w))
except Exception as ei:
logger.exception("视频格式异常:{}", ei)
result = cv2.cvtColor(img, cv2.COLOR_YUV2BGR_NV12)
except Exception as e:
logger.exception("读流异常:{}", e)
return result
def close(self):
if self.pull_p:
if self.pull_p.stdout:
self.pull_p.stdout.close()
self.pull_p.terminate()
self.pull_p.wait()
logger.info("关闭拉流管道完成, requestId:{}", self.requestId)
if self.p:
if self.p.stdin:
self.p.stdin.close()
self.p.terminate()
self.p.wait()
# self.p.communicate()
# self.p.kill()
logger.info("关闭管道完成, requestId:{}", self.requestId)
if self.or_video_file:
self.or_video_file.release()
logger.info("关闭原视频写入流完成, requestId:{}", self.requestId)
if self.ai_video_file:
self.ai_video_file.release()
logger.info("关闭AI视频写入流完成, requestId:{}", self.requestId)
# async def push_stream_write(self, frame):
# self.p.stdin.write(frame.tostring())
#
# async def push_stream(self, frame):
# if self.p is None:
# self.build_p()
# try:
# await self.push_stream_write(frame)
# return True
# except Exception as ex:
# logger.exception("推流进管道异常:{}, requestId: {}", ex, self.requestId)
# current_retry_num = 0
# while True:
# try:
# time.sleep(1)
# self.p_push_retry_num += 1
# current_retry_num += 1
# if current_retry_num > 3 or self.p_push_retry_num > 600:
# return False
# self.build_p()
# await self.push_stream_write(frame)
# logger.info("构建p管道重试成功, 当前重试次数: {}, requestId: {}", current_retry_num,
# self.requestId)
# return True
# except Exception as e:
# logger.exception("构建p管道异常{}, 开始重试, 当前重试次数:{}, requestId: {}", e,
# current_retry_num, self.requestId)
# return False
# async def video_frame_write(self, or_frame, ai_frame):
# if or_frame is not None:
# self.or_video_file.write(or_frame)
# if ai_frame is not None:
# self.ai_video_file.write(ai_frame)
# async def video_write(self, or_frame, ai_frame):
# try:
# self.build_write()
# if or_frame is not None and len(or_frame) > 0:
# await self.video_frame_write(or_frame, None)
# if ai_frame is not None and len(ai_frame) > 0:
# await self.video_frame_write(None, ai_frame)
# return True
# except Exception as ex:
# ai_retry_num = 0
# while True:
# try:
# ai_retry_num += 1
# if ai_retry_num > 3:
# logger.exception("重新写入离线分析后视频到本地,重试失败:{}, requestId: {}", e, self.requestId)
# return False
# if or_frame is not None and len(or_frame) > 0:
# await self.or_video_file.write(or_frame)
# if ai_frame is not None and len(ai_frame) > 0:
# await self.ai_video_file.write(ai_frame)
# logger.info("重新写入离线分析后视频到本地, 当前重试次数: {}, requestId: {}", ai_retry_num,
# self.requestId)
# return True
# except Exception as e:
# logger.exception("重新写入离线分析后视频到本地:{}, 开始重试, 当前重试次数:{}, requestId: {}", e,
# ai_retry_num, self.requestId)
# def build_write(self):
# try:
# if self.fps is None or self.width is None or self.height is None:
# raise ServiceException(ExceptionType.VIDEO_CONFIG_EXCEPTION.value[0],
# ExceptionType.VIDEO_CONFIG_EXCEPTION.value[1])
# if self.orFilePath is not None and self.or_video_file is None:
# self.or_video_file = cv2.VideoWriter(self.orFilePath, cv2.VideoWriter_fourcc(*'mp4v'), self.fps,
# (int(self.wn), int(self.hn)))
# if self.or_video_file is None:
# raise ServiceException(ExceptionType.OR_WRITE_OBJECT_EXCEPTION.value[0],
# ExceptionType.OR_WRITE_OBJECT_EXCEPTION.value[1])
# if self.aiFilePath is not None and self.ai_video_file is None:
# self.ai_video_file = cv2.VideoWriter(self.aiFilePath, cv2.VideoWriter_fourcc(*'mp4v'), self.fps,
# (int(self.width), int(self.hn)))
# if self.ai_video_file is None:
# raise ServiceException(ExceptionType.AI_WRITE_OBJECT_EXCEPTION.value[0],
# ExceptionType.AI_WRITE_OBJECT_EXCEPTION.value[1])
# except ServiceException as s:
# logger.exception("构建文件写对象异常: {}, requestId:{}", s, self.requestId)
# raise s
# except Exception as e:
# logger.exception("构建文件写对象异常: {}, requestId:{}", e, self.requestId)
# raise e
# def video_merge(self, frame1, frame2):
# # frameLeft = cv2.resize(frame1, (int(self.width / 2), int(self.height / 2)), interpolation=cv2.INTER_LINEAR)
# # frameRight = cv2.resize(frame2, (int(self.width / 2), int(self.height / 2)), interpolation=cv2.INTER_LINEAR)
# # frame_merge = np.hstack((frameLeft, frameRight))
# frame_merge = np.hstack((frame1, frame2))
# return frame_merge
#
# def getP(self):
# if self.p is None:
# logger.error("获取管道为空, requestId:{}", self.requestId)
# raise ServiceException(ExceptionType.PULL_PIPELINE_INIT_EXCEPTION.value[0],
# ExceptionType.PULL_PIPELINE_INIT_EXCEPTION.value[1])
# return self.p
#
# def getCap(self):
# if self.cap is None:
# logger.error("获取cv2为空, requestId:{}", self.requestId)
# raise ServiceException(ExceptionType.CV2_IS_NULL_EXCEPTION.value[0],
# ExceptionType.CV2_IS_NULL_EXCEPTION.value[1])
# return self.cap
#
# def getOrVideoFile(self):
# if self.or_video_file is None:
# logger.error("获取原视频写入对象为空, requestId:{}", self.requestId)
# raise ServiceException(ExceptionType.OR_WRITE_OBJECT_EXCEPTION.value[0],
# ExceptionType.OR_WRITE_OBJECT_EXCEPTION.value[1])
# return self.or_video_file
#
# def getAiVideoFile(self):
# if self.ai_video_file is None:
# logger.error("获取AI视频写入对象为空, requestId:{}", self.requestId)
# raise ServiceException(ExceptionType.AI_WRITE_OBJECT_EXCEPTION.value[0],
# ExceptionType.AI_WRITE_OBJECT_EXCEPTION.value[1])
# return self.ai_video_file
if __name__== "__main__":
command = ['ffmpeg',
'-rtsp_transport', 'tcp',
'-i', 'rtsp://127.0.0.1:8554/video', # 指定输入文件
'-c', 'copy',
'-f', 'flv',
"rtmp://192.168.10.101:19350/rlive/stream_9?sign=f8a15b6n"]
p = sp.Popen(command, shell=False)
while True:
time.sleep(2)
print("pid", p.pid)
print("poll", p.poll())
print("returncode", p.returncode)
# p.terminate()
# p.wait()