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

feat: 萤石云云录制

上级 b897fa12
...@@ -5,4 +5,10 @@ PROCESSING_TOTAL_KEY = 'hk_isc:recording:processing:total' ...@@ -5,4 +5,10 @@ PROCESSING_TOTAL_KEY = 'hk_isc:recording:processing:total'
ACCOUNT_TOKEN_KEY = 'eviz:account:app_key:{}:token' ACCOUNT_TOKEN_KEY = 'eviz:account:app_key:{}:token'
DEVICE_SERIAL_KEY = 'eviz:account:device:{}' DEVICE_SERIAL_KEY = 'eviz:account:device:{}'
UNTREATED_JOB_KEY = 'eviz:camera:{}:cloud_download'
UNVERIFIED_FILE_KEY = 'eviz:unverified:{}:file:{}'
RECORDING_JOB_KEY = 'eviz:camera:{}:recording'
UNVERIFIED_EVENT_QUEUE = 'UNVERIFIED_EVENT_QUEUE' UNVERIFIED_EVENT_QUEUE = 'UNVERIFIED_EVENT_QUEUE'
RECORD_TASK_QUEUE = 'RECORD_TASK_QUEUE'
...@@ -137,7 +137,7 @@ def get_camera_info(cursor, conn, camera_code=None, platform='isc', video_plan_t ...@@ -137,7 +137,7 @@ def get_camera_info(cursor, conn, camera_code=None, platform='isc', video_plan_t
@query() @query()
def insert_video_info(cursor, conn, db_table, device_code, start_time, end_time, def insert_video_info(cursor, conn, db_table, device_code, start_time, end_time,
biz_type, service_type, status=0, biz_type, service_type, status=0,
file_name=None, video_url=None, video_resolution=None, recovered_time=None): file_name=None, video_url=None, video_resolution=None, recovered_time=None, record_type='event'):
sql = ''' sql = '''
insert {} ( insert {} (
device_code, file_name, start_time, end_time, device_code, file_name, start_time, end_time,
......
差异被折叠。
...@@ -435,6 +435,7 @@ class ProcessMessage: ...@@ -435,6 +435,7 @@ class ProcessMessage:
_, error_log = record_thread(stream_url, file_name, thread_name=body['camera_code']) _, error_log = record_thread(stream_url, file_name, thread_name=body['camera_code'])
video_info, video_error_log = judge_video_error(file_name) video_info, video_error_log = judge_video_error(file_name)
if video_error_log: if video_error_log:
# TODO 文件损害说明
log.warning('file: %s, error_log: %s', file_name, video_error_log) log.warning('file: %s, error_log: %s', file_name, video_error_log)
video_duration = time_to_seconds(video_info['duration']) video_duration = time_to_seconds(video_info['duration'])
if video_duration > 5: if video_duration > 5:
......
...@@ -48,11 +48,19 @@ def command_line_runner(): ...@@ -48,11 +48,19 @@ def command_line_runner():
elif args['worker'] == 'merger': elif args['worker'] == 'merger':
from ils_common_video.eviz_video.merger import main as record_main from ils_common_video.eviz_video.merger import main as record_main
record_main() record_main()
elif args['worker'] == 'downloader':
from ils_common_video.eviz_video.cloud_download import DownloadFileJob
dfj = DownloadFileJob()
dfj.start()
elif args['env'] == 'common': elif args['env'] == 'common':
if args['worker'] == 'filter': if args['worker'] == 'filter':
from ils_common_video.video_filter.filter import VideoFilterProcess from ils_common_video.video_filter.filter import VideoFilterProcess
fp = VideoFilterProcess() fp = VideoFilterProcess()
fp.run() fp.run()
elif args['worker'] == 'record_task':
from ils_common_video.record_task import RecordTaskListener
rtr = RecordTaskListener()
rtr.run()
else: else:
parser.print_help() parser.print_help()
......
import json
import time
import dateutil.parser
from datetime import datetime
from intelab_python_sdk.logger import log
from ils_common_video.db.rabbitmq import rabbitmq_connect
from ils_common_video.const import RECORD_TASK_QUEUE, UNTREATED_JOB_KEY
from ils_common_video.db.redis import redis_connect
from ils_common_video.db import mysql
class RecordTaskListener:
def __init__(self):
self.queue_name = RECORD_TASK_QUEUE
self.connection = rabbitmq_connect()
self.channel = self.connection.channel()
def run(self):
log.info('启动分析进程')
log.info('binding to queue {}'.format(self.queue_name))
self.channel.queue_declare(queue=self.queue_name, durable=True)
def callback(ch, method, properties, body):
log.info('received MQ message {}'.format(body))
try:
body = json.loads(body)
# TODO 摄像头没有绑定业务的需要处理吗?
camera_info = mysql.get_camera_info(camera_code=body['camera_code'], platform=None)
if camera_info:
platform = camera_info[0]['platform']
camera_info[0].update({
'ex': body['end_time'] - body['start_time'],
'retry': True
})
body['start_time'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(body['start_time']))
body['end_time'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(body['end_time']))
camera_info[0].update(body)
event_id = self.insert_pending_event(camera_info[0])
camera_info[0].update({'event_id': event_id})
if platform == 'eviz':
# 萤石云的云录制,直接设置任务key就可以
self.set_eviz_cloud_record_job(camera_info[0])
else:
# ISC协议摄像头需要丢进任务队列
self.channel.basic_publish(exchange='', routing_key='ISC_CLOUD_RECORD',
body=json.dumps(camera_info[0], ensure_ascii=False))
log.info('finished processing MQ message')
ch.basic_ack(delivery_tag=method.delivery_tag)
except Exception as e:
log.exception(e)
log.error('finished processing MQ message, error')
self.channel.basic_qos(prefetch_count=1)
self.channel.basic_consume(on_message_callback=callback,
queue=self.queue_name)
log.info(' [*] Waiting for messages. To exit press CTRL+C')
try:
self.channel.start_consuming()
except KeyboardInterrupt:
log.info('MQ connection closed by user')
except Exception as e:
log.exception('MQ connection closed unexpectedly. %s', e)
raise
self.connection.close()
@staticmethod
def insert_pending_event(body):
event_id = mysql.insert_video_info(
body['db_table'], body['device_code'], body['start_time'],
body['end_time'], biz_type=body['biz_type'],
service_type=body['service_type'], status=3, record_type='task'
)
return event_id
@staticmethod
def set_eviz_cloud_record_job(body):
pipe = redis_connect()
start_time = dateutil.parser.parse(body['start_time'])
end_time = dateutil.parser.parse(body['end_time'])
file_id = body['camera_code'] + start_time.strftime('%Y%m%d%H%M%S')
event_duration = int((end_time - start_time).total_seconds())
log.info('file_id: {}, start_time: {}, end_time: {}, duration: {}'.format(
file_id, start_time, end_time, event_duration))
# TODO 可以使用异步任务框架
body.update({
'file_id': file_id,
'create_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'duration': event_duration,
'status': 0,
})
pipe.lpush(UNTREATED_JOB_KEY.format(body['camera_code']), json.dumps(body, ensure_ascii=False))
pipe.close()
...@@ -117,7 +117,7 @@ def judge_video_error(file_name): ...@@ -117,7 +117,7 @@ def judge_video_error(file_name):
def get_video_duration(file_name, start_time='00:00:00', key_word='block unavailable'): 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' resolution, duration, bitrate, media_type = ['0x0'], ['00:00:00'], ['0'], 'VideoHandler'
size, error_log = 0, '' size, error_log, fps = 0, '', ['0']
log_buffer = subprocess.getoutput( log_buffer = subprocess.getoutput(
'ffmpeg -y -ss {} -i {} -t 1 -vframes 1 /tmp/tmp.jpg'.format(start_time, file_name)) 'ffmpeg -y -ss {} -i {} -t 1 -vframes 1 /tmp/tmp.jpg'.format(start_time, file_name))
...@@ -134,6 +134,7 @@ def get_video_duration(file_name, start_time='00:00:00', key_word='block unavail ...@@ -134,6 +134,7 @@ def get_video_duration(file_name, start_time='00:00:00', key_word='block unavail
duration = re.findall(r'Duration: (\d\d:\d\d:\d\d)\.\d\d', log_buffer) or duration 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 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 resolution = re.findall(r'(\d{3,4}x\d{3,4})', log_buffer) or resolution
fps = re.findall(r', (\d+) fps,', log_buffer) or fps
if 'SoundHandler' in log_buffer: if 'SoundHandler' in log_buffer:
media_type += '+SoundHandler' media_type += '+SoundHandler'
...@@ -143,6 +144,11 @@ def get_video_duration(file_name, start_time='00:00:00', key_word='block unavail ...@@ -143,6 +144,11 @@ def get_video_duration(file_name, start_time='00:00:00', key_word='block unavail
video_info = { video_info = {
'duration': duration[0], 'bitrate': bitrate[0], 'duration': duration[0], 'bitrate': bitrate[0],
'resolution': resolution[0], 'media_type': media_type, 'resolution': resolution[0], 'media_type': media_type,
'file_name': file_name, 'size': round(size, 2) 'file_name': file_name, 'size': round(size, 2),
'fps': fps[0]
} }
return video_info, error_log return video_info, error_log
if __name__ == '__main__':
print(get_video_duration('/tmp/videos/D86639983/D86639983_2021-08-12_14-06-42.mp4'))
...@@ -10,8 +10,8 @@ client = HikVisionClient(config.get('KEY'), config.get('SECRET'), ...@@ -10,8 +10,8 @@ client = HikVisionClient(config.get('KEY'), config.get('SECRET'),
# with open('camera_infos.json', 'r+') as f: # with open('camera_infos.json', 'r+') as f:
# json.dump(client.get_cameras(), f, indent=4, ensure_ascii=False) # json.dump(client.get_cameras(), f, indent=4, ensure_ascii=False)
# #
for camera in client.get_cameras(): for camera in [{'indexCode': '9ce74c6cfa114f6c86f97bd58377409d'}]:
print(camera) print(camera)
url = client.get_camera_preview_url(camera['indexCode'], protocol='rtsp', stream_type=1) url = client.get_camera_preview_url(camera['indexCode'], protocol='rtsp', stream_type=0)
print('摄像头{}的直播地址为{}'.format(camera['indexCode'], url.get('url'))) print('摄像头{}的直播地址为{}'.format(camera['indexCode'], url.get('url')))
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论