提交 09c4d42d authored 作者: zw.wang's avatar zw.wang

feat: [recorder] 检查录制的视频文件,文件存在问题时发送报警

上级 6c0044ef
...@@ -16,7 +16,7 @@ from isc_video_record.const import PROCESSING_CAMERA_KEY ...@@ -16,7 +16,7 @@ from isc_video_record.const import PROCESSING_CAMERA_KEY
from isc_video_record.utils.api_helper import IntelabApiHelper, PlaybackUrlException from isc_video_record.utils.api_helper import IntelabApiHelper, PlaybackUrlException
from isc_video_record.utils.isc_client import HikVisionClient from isc_video_record.utils.isc_client import HikVisionClient
from isc_video_record.utils import aliyun_oss from isc_video_record.utils import aliyun_oss
from isc_video_record.utils.record_utils import record_thread, get_video_duration, time_to_seconds from isc_video_record.utils.record_utils import record_thread, get_video_duration, time_to_seconds, judge_video_error
from isc_video_record.utils.alarm_utils import send_alarm_to_developer from isc_video_record.utils.alarm_utils import send_alarm_to_developer
from isc_video_record.db import mysql from isc_video_record.db import mysql
...@@ -307,8 +307,8 @@ class ProcessMessage: ...@@ -307,8 +307,8 @@ class ProcessMessage:
retry_count += 1 retry_count += 1
complete_duration = (end_time - start_time).total_seconds() complete_duration = (end_time - start_time).total_seconds()
(file_info, _), error_log = self.stream_record(playback_stream['stream_url'], file_info, error_log = self.stream_record(playback_stream['stream_url'],
start_time, end_time) start_time, end_time)
if error_log: if error_log:
remark += ' ' + error_log remark += ' ' + error_log
...@@ -369,9 +369,14 @@ class ProcessMessage: ...@@ -369,9 +369,14 @@ class ProcessMessage:
file_name = os.path.join( file_name = os.path.join(
video_path, 'rtmp_{}_{}_{}.mp4'.format(self.body['camera_code'], start_time, end_time)) video_path, 'rtmp_{}_{}_{}.mp4'.format(self.body['camera_code'], start_time, end_time))
log.info('%s:stream_url: %s', self.body['camera_code'], stream_url) log.info('%s:stream_url: %s', self.body['camera_code'], stream_url)
# TODO 多进程处理 # TODO 出现ffmpeg进程阻塞的情况
_, error_log = record_thread(stream_url, file_name, thread_name=self.body['camera_code']) _, error_log = record_thread(stream_url, file_name, thread_name=self.body['camera_code'])
return get_video_duration(file_name), error_log video_info, video_error_log = judge_video_error(file_name)
# TODO 查看出现损坏的视频发送报警
if video_error_log:
send_alarm_to_developer('recorder', 'file_name: {}, error_log: {}'.format(file_name, video_error_log),
mobiles=['15131601294'])
return video_info, error_log
@staticmethod @staticmethod
def write_retry_info_to_influx(camera_code, error_log): def write_retry_info_to_influx(camera_code, error_log):
......
...@@ -3,20 +3,19 @@ from threading import Thread ...@@ -3,20 +3,19 @@ from threading import Thread
from intelab_python_sdk.dingtalk import DingTalkMessage from intelab_python_sdk.dingtalk import DingTalkMessage
def send_alarm_to_developer(service_name, e): def send_alarm_to_developer(service_name, e, mobiles=None):
config = settings.get('DINGTALK')
mobiles = mobiles or config.get('MOBILES')
dingtalk_config = settings.get('DINGTALK') if isinstance(e, Exception):
dingtalk_mobiles = dingtalk_config.get('MOBILES') import traceback
dingtalk = DingTalkMessage(dingtalk_config.get('WEBHOOK'), content = '告警::\n{}服务模块出错:\n {}'.format(
dingtalk_config.get('SECRET')) service_name, traceback.format_exc())
import traceback else:
content = '告警::\n{}服务模块出错:\n {}'.format( content = e
service_name, traceback.format_exc())
t = Thread(target=dingtalk.send_text, args=( dt = DingTalkMessage(config.get('WEBHOOK'), config.get('SECRET'))
content, dingtalk_mobiles, False Thread(target=dt.send_text, args=(content, mobiles, False)).start()
))
t.start()
def send_markdown(title, text, mobiles=None): def send_markdown(title, text, mobiles=None):
......
...@@ -66,41 +66,6 @@ def record_thread(stream_url, out_file, thread_name='ffmpeg-log', protocol='rtmp ...@@ -66,41 +66,6 @@ def record_thread(stream_url, out_file, thread_name='ffmpeg-log', protocol='rtmp
return out_file, error_log return out_file, error_log
def get_video_duration(file_name):
"""
获取视频文件的持续时间、分辨率等信息
"""
error_log = ''
duration = ['00:00:00']
bitrate = ['0']
resolution = ['0x0']
media_type = 'VideoHandler'
size = 0
log_buffer = subprocess.getoutput('ffmpeg -i {}'.format(file_name))
if 'moov atom not found' in log_buffer:
error_log += log_buffer
duration = re.findall(r'Duration: (\d\d:\d\d:\d\d)\.\d\d',
log_buffer) or duration
bitrate = re.findall(r'bitrate: (\d+) kb/s',
log_buffer) or bitrate
resolution = re.findall(r'(\d{3,4}x\d{3,4})', log_buffer) or resolution
if 'SoundHandler' in log_buffer:
media_type += '+SoundHandler'
if os.path.isfile(file_name):
size = os.path.getsize(file_name) / 1024.0 / 1024.0
video_info = {
'duration': duration[0],
'bitrate': bitrate[0],
'resolution': resolution[0],
'media_type': media_type,
'file_name': file_name,
'size': size
}
return video_info, error_log
def time_to_seconds(duration): def time_to_seconds(duration):
""" """
时间字符串转换成秒 时间字符串转换成秒
...@@ -135,3 +100,48 @@ def get_time_str(seconds): ...@@ -135,3 +100,48 @@ def get_time_str(seconds):
s += str(':%02d' % seconds) s += str(':%02d' % seconds)
return s return s
def judge_video_error(file_name):
"""
:param file_name: 文件路径
:return duration, bitrate, error_log
"""
# 通过ffmpeg打开文件两次判定文件是否花屏
video_info, error_log = get_video_duration(file_name)
*_, error_log = get_video_duration(file_name, video_info['duration'])\
if not error_log else (video_info, error_log)
return video_info, error_log
def get_video_duration(file_name, start_time='00:00:00', key_word='block unavailable'):
resolution, duration, bitrate, media_type = ['0x0'], ['00:00:00'], ['0'], 'VideoHandler'
size, error_log = 0, ''
log_buffer = subprocess.getoutput(
'ffmpeg -y -ss {} -i {} -t 1 -vframes 1 /tmp/tmp.jpg'.format(start_time, file_name))
if 'moov atom not found' in log_buffer:
error_log += log_buffer
if 'Impossible to open' in log_buffer:
error_log = log_buffer
if key_word in log_buffer:
error_log = log_buffer
if 'errors in I frame' in log_buffer:
error_log += log_buffer
duration = re.findall(r'Duration: (\d\d:\d\d:\d\d)\.\d\d', log_buffer) or duration
bitrate = re.findall(r'bitrate: (\d+) kb/s', log_buffer) or bitrate
resolution = re.findall(r'(\d{3,4}x\d{3,4})', log_buffer) or resolution
if 'SoundHandler' in log_buffer:
media_type += '+SoundHandler'
if os.path.isfile(file_name):
size = os.path.getsize(file_name) / 1024.0 / 1024.0
video_info = {
'duration': duration[0], 'bitrate': bitrate[0],
'resolution': resolution[0], 'media_type': media_type,
'file_name': file_name, 'size': round(size, 2)
}
return video_info, error_log
...@@ -24,7 +24,7 @@ requires = [ ...@@ -24,7 +24,7 @@ requires = [
setuptools.setup( setuptools.setup(
name='isc-video-record', name='isc-video-record',
version='1.0.0b13', version='1.0.0b14',
description='ISC motion detection playback video stream recording service.', description='ISC motion detection playback video stream recording service.',
long_description=long_description, long_description=long_description,
long_description_content_type='text/markdown', long_description_content_type='text/markdown',
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论