Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
I
ils-common-video
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
提交
议题看板
打开侧边栏
OpsTeam
ils-common-video
Commits
68c43cf6
提交
68c43cf6
authored
6月 15, 2021
作者:
zw.wang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: [merger] 根据摄像头的录像计划使用不同的方案
上级
eb4be60f
显示空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
65 行增加
和
28 行删除
+65
-28
mysql.py
isc_video_record/db/mysql.py
+2
-1
merger.py
isc_video_record/merger.py
+15
-6
recorder.py
isc_video_record/recorder.py
+1
-1
isc_client.py
isc_video_record/utils/isc_client.py
+7
-6
pre_event.py
isc_video_record/utils/pre_event.py
+1
-1
setup.py
setup.py
+1
-1
test_playback.py
tests/test_playback.py
+38
-12
没有找到文件。
isc_video_record/db/mysql.py
浏览文件 @
68c43cf6
...
@@ -89,7 +89,8 @@ def get_camera_info(cursor, conn):
...
@@ -89,7 +89,8 @@ def get_camera_info(cursor, conn):
'video_data_motion_', mod(biz_type, 8)
'video_data_motion_', mod(biz_type, 8)
) as 'db_table',
) as 'db_table',
ai_config_support, device_code, service_type, biz_type,
ai_config_support, device_code, service_type, biz_type,
region_path_name
region_path_name,
1 as video_plan_type
from camera_info
from camera_info
join camera_ai_config cac
join camera_ai_config cac
on camera_info.id = cac.camera_info_id
on camera_info.id = cac.camera_info_id
...
...
isc_video_record/merger.py
浏览文件 @
68c43cf6
...
@@ -40,10 +40,7 @@ class EventMergerJob:
...
@@ -40,10 +40,7 @@ class EventMergerJob:
time
.
strftime
(
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S"
,
time
.
localtime
(
next_run_at
)))
time
.
strftime
(
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S"
,
time
.
localtime
(
next_run_at
)))
time
.
sleep
(
15
*
60
)
time
.
sleep
(
15
*
60
)
def
get_camera_local_events
(
self
,
pipe
,
camera
,
now
):
def
get_scan_time
(
self
,
pipe
,
camera
,
now
):
"""
获取摄像头本地移动侦测事件
"""
last_check_time_key
=
LAST_CHECK_TIME_KEY
.
format
(
camera
[
'device_code'
])
last_check_time_key
=
LAST_CHECK_TIME_KEY
.
format
(
camera
[
'device_code'
])
last_check_time
=
pipe
.
get
(
last_check_time_key
)
last_check_time
=
pipe
.
get
(
last_check_time_key
)
if
not
last_check_time
:
if
not
last_check_time
:
...
@@ -60,7 +57,13 @@ class EventMergerJob:
...
@@ -60,7 +57,13 @@ class EventMergerJob:
if
now
-
last_check_time
>
timedelta
(
days
=
1
):
if
now
-
last_check_time
>
timedelta
(
days
=
1
):
# 时间跨度超过一天,则分割成两个小时
# 时间跨度超过一天,则分割成两个小时
now
=
last_check_time
+
timedelta
(
hours
=
2
)
now
=
last_check_time
+
timedelta
(
hours
=
2
)
return
last_check_time
,
now
def
get_camera_local_events
(
self
,
pipe
,
camera
,
now
):
"""
获取摄像头本地移动侦测事件
"""
last_check_time
,
now
=
self
.
get_scan_time
(
pipe
,
camera
,
now
)
events
=
[]
events
=
[]
try
:
try
:
log
.
info
(
'查询摄像头
%
s在
%
s,
%
s的本地视频文件'
,
camera
[
'device_code'
],
log
.
info
(
'查询摄像头
%
s在
%
s,
%
s的本地视频文件'
,
camera
[
'device_code'
],
...
@@ -82,6 +85,7 @@ class EventMergerJob:
...
@@ -82,6 +85,7 @@ class EventMergerJob:
# TODO 网络请求错误重试
# TODO 网络请求错误重试
log
.
exception
(
e
)
log
.
exception
(
e
)
else
:
else
:
last_check_time_key
=
LAST_CHECK_TIME_KEY
.
format
(
camera
[
'device_code'
])
res
=
pipe
.
set
(
last_check_time_key
,
res
=
pipe
.
set
(
last_check_time_key
,
now
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
))
now
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
))
if
not
res
:
if
not
res
:
...
@@ -101,12 +105,14 @@ class EventMergerJob:
...
@@ -101,12 +105,14 @@ class EventMergerJob:
self
.
send_mq_message
(
body
)
self
.
send_mq_message
(
body
)
return
body
.
get
(
'ex'
,
0
)
return
body
.
get
(
'ex'
,
0
)
def
get_
new_events
(
self
,
last_check_time
,
now
,
camera
):
def
get_
alarm_events
(
self
,
pipe
,
camera
,
now
):
"""
"""
摄像头录制计划为全天录制时
摄像头录制计划为全天录制时
查询指定时间段内摄像头是否有移动告警消息并合并成事件
查询指定时间段内摄像头是否有移动告警消息并合并成事件
"""
"""
last_check_time
,
now
=
self
.
get_scan_time
(
pipe
,
camera
,
now
)
pre_event
=
PreEvent
(
pre_event
=
PreEvent
(
last_check_time
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
),
last_check_time
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
),
now
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
)
now
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
)
...
@@ -135,7 +141,10 @@ class EventMergerJob:
...
@@ -135,7 +141,10 @@ class EventMergerJob:
event_duration
=
self
.
look_untreated_events
(
camera
,
body
)
event_duration
=
self
.
look_untreated_events
(
camera
,
body
)
if
event_duration
==
0
:
if
event_duration
==
0
:
for
event
in
self
.
get_camera_local_events
(
pipe
,
camera
,
now
):
call_get_events_func
=
self
.
get_alarm_events
if
camera
[
'video_plan_type'
]
==
1
else
\
self
.
get_cameras_playback_urls
for
event
in
call_get_events_func
(
pipe
,
camera
,
now
):
insert_video_info
(
insert_video_info
(
camera
[
'db_table'
],
camera
[
'device_code'
],
camera
[
'db_table'
],
camera
[
'device_code'
],
event
[
'start_time'
]
.
astimezone
(
pytz
.
utc
),
event
[
'start_time'
]
.
astimezone
(
pytz
.
utc
),
...
...
isc_video_record/recorder.py
浏览文件 @
68c43cf6
...
@@ -21,7 +21,7 @@ from isc_video_record.db import mysql
...
@@ -21,7 +21,7 @@ from isc_video_record.db import mysql
tz
=
pytz
.
timezone
(
'Asia/Shanghai'
)
tz
=
pytz
.
timezone
(
'Asia/Shanghai'
)
video_path
=
'/
data
/videos/isc-record'
video_path
=
'/
tmp
/videos/isc-record'
os
.
makedirs
(
video_path
,
exist_ok
=
True
)
os
.
makedirs
(
video_path
,
exist_ok
=
True
)
api_helper
=
IntelabApiHelper
()
api_helper
=
IntelabApiHelper
()
...
...
isc_video_record/utils/isc_client.py
浏览文件 @
68c43cf6
...
@@ -10,6 +10,7 @@ from time import mktime
...
@@ -10,6 +10,7 @@ from time import mktime
from
email.utils
import
formatdate
from
email.utils
import
formatdate
from
requests.packages
import
urllib3
from
requests.packages
import
urllib3
from
intelab_python_sdk.logger
import
log
from
intelab_python_sdk.logger
import
log
from
isc_video_record.utils.api_helper
import
PlaybackUrlException
class
HikVisionClient
(
object
):
class
HikVisionClient
(
object
):
...
@@ -51,16 +52,16 @@ class HikVisionClient(object):
...
@@ -51,16 +52,16 @@ class HikVisionClient(object):
response
=
requests
.
post
(
url
,
headers
=
self
.
_sign
(
uri
,
body
,
'POST'
),
response
=
requests
.
post
(
url
,
headers
=
self
.
_sign
(
uri
,
body
,
'POST'
),
json
=
body
,
verify
=
False
,
timeout
=
30
)
json
=
body
,
verify
=
False
,
timeout
=
30
)
data
=
{}
data
=
{}
response
.
raise_for_status
()
if
response
.
status_code
==
200
:
if
response
.
status_code
==
200
:
data
[
'code'
]
=
200
data
[
'code'
]
=
200
res_json
=
response
.
json
()
res_json
=
response
.
json
()
if
res_json
.
get
(
'code'
,
'0x000000'
)
==
'0'
:
if
res_json
.
get
(
'code'
,
'0'
)
!=
'0'
:
raise
PlaybackUrlException
(
res_json
)
if
'data'
in
res_json
:
if
'data'
in
res_json
:
data
=
res_json
[
'data'
]
data
=
res_json
[
'data'
]
else
:
log
.
warning
(
res_json
[
'msg'
])
else
:
log
.
error
(
'error:
%
s'
,
response
.
text
)
return
data
return
data
def
get_camera_preview_url
(
self
,
camera_index_code
,
def
get_camera_preview_url
(
self
,
camera_index_code
,
...
@@ -128,7 +129,7 @@ class HikVisionClient(object):
...
@@ -128,7 +129,7 @@ class HikVisionClient(object):
'recordLocation'
:
1
,
'recordLocation'
:
1
,
'protocol'
:
protocol
,
'protocol'
:
protocol
,
'expand'
:
'fileSize=1024'
,
'expand'
:
'fileSize=1024'
,
'streamform'
:
streamform
'streamform'
:
streamform
,
}
}
log
.
info
(
'requests body: {}'
.
format
(
body
))
log
.
info
(
'requests body: {}'
.
format
(
body
))
expired_time
=
datetime
.
now
()
+
timedelta
(
minutes
=
5
)
expired_time
=
datetime
.
now
()
+
timedelta
(
minutes
=
5
)
...
...
isc_video_record/utils/pre_event.py
浏览文件 @
68c43cf6
...
@@ -44,7 +44,7 @@ class PreEvent(object):
...
@@ -44,7 +44,7 @@ class PreEvent(object):
# 合并告警消息最小单位60s
# 合并告警消息最小单位60s
# TODO 事件的开始和结束需要依赖于status,status=1触发,status=2结束
# TODO 事件的开始和结束需要依赖于status,status=1触发,status=2结束
if
len
(
events
)
>
0
\
if
len
(
events
)
>
0
\
and
alarm_time
-
events
[
-
1
][
'end_time'
]
<
timedelta
(
seconds
=
6
0
)
\
and
alarm_time
-
events
[
-
1
][
'end_time'
]
<
timedelta
(
seconds
=
3
0
)
\
and
events
[
-
1
][
'end_time'
]
-
events
[
-
1
][
'start_time'
]
<
timedelta
(
hours
=
0.5
):
and
events
[
-
1
][
'end_time'
]
-
events
[
-
1
][
'start_time'
]
<
timedelta
(
hours
=
0.5
):
events
[
-
1
][
'end_time'
]
=
alarm_time
+
timedelta
(
seconds
=
10
)
events
[
-
1
][
'end_time'
]
=
alarm_time
+
timedelta
(
seconds
=
10
)
continue
continue
...
...
setup.py
浏览文件 @
68c43cf6
...
@@ -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.0b
1
'
,
version
=
'1.0.0b
2
'
,
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'
,
...
...
tests/test_playback.py
浏览文件 @
68c43cf6
...
@@ -6,11 +6,13 @@ from dynaconf import settings
...
@@ -6,11 +6,13 @@ from dynaconf import settings
from
isc_video_record.utils.isc_client
import
HikVisionClient
from
isc_video_record.utils.isc_client
import
HikVisionClient
from
isc_video_record.utils.record_utils
import
record_thread
,
get_video_duration
from
isc_video_record.utils.record_utils
import
record_thread
,
get_video_duration
from
isc_video_record.utils.api_helper
import
PlaybackUrlException
from
isc_video_record.utils.pre_event
import
PreEvent
tz
=
pytz
.
timezone
(
'Asia/Shanghai'
)
tz
=
pytz
.
timezone
(
'Asia/Shanghai'
)
log_init
(
__name__
,
True
,
'./log'
)
log_init
(
__name__
,
True
,
'./log'
)
video_path
=
'/
data
/videos/isc-record'
video_path
=
'/
tmp
/videos/isc-record'
os
.
makedirs
(
video_path
,
exist_ok
=
True
)
os
.
makedirs
(
video_path
,
exist_ok
=
True
)
config
=
settings
.
get
(
'ISC'
)
config
=
settings
.
get
(
'ISC'
)
...
@@ -21,19 +23,43 @@ client = HikVisionClient(config.get('KEY'), config.get('SECRET'),
...
@@ -21,19 +23,43 @@ client = HikVisionClient(config.get('KEY'), config.get('SECRET'),
def
main
():
def
main
():
start_time
=
datetime
(
2021
,
5
,
27
,
9
,
10
,
30
)
.
astimezone
(
tz
)
start_time
=
datetime
(
2021
,
6
,
11
,
9
,
27
,
21
)
.
astimezone
(
tz
)
# start_time = datetime(2021, 5, 28, 9, 10, 59).astimezone(tz)
# start_time = datetime(2021, 5, 28, 9, 10, 59).astimezone(tz)
end_time
=
datetime
(
2021
,
5
,
27
,
9
,
30
,
50
)
.
astimezone
(
tz
)
end_time
=
datetime
(
2021
,
6
,
11
,
18
,
30
,
50
)
.
astimezone
(
tz
)
res
=
client
.
get_cameras_playback_urls
(
'8f50e406cad6489fac443e034d29a66f'
,
camera_index
=
'bb954401e1e9420d91e4b3691566f161'
client
.
iso_format
(
start_time
),
client
.
iso_format
(
end_time
))
results
=
[]
try
:
res
=
client
.
get_cameras_playback_urls
(
camera_index
,
client
.
iso_format
(
start_time
),
client
.
iso_format
(
end_time
)
)
results
.
extend
(
res
)
except
PlaybackUrlException
as
e
:
if
'Internal Error'
in
e
.
msg
:
pre_events
=
PreEvent
(
start_time
.
astimezone
(
pytz
.
utc
)
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
),
end_time
.
astimezone
(
pytz
.
utc
)
.
strftime
(
'
%
Y-
%
m-
%
d
%
H:
%
M:
%
S'
))
unverified_events
=
pre_events
.
merge_alarm_to_event
(
pre_events
.
get_alarm_list
(
camera_index
))
for
event
in
unverified_events
:
try
:
res
=
client
.
get_cameras_playback_urls
(
camera_index
,
client
.
iso_format
(
event
[
'start_time'
]),
client
.
iso_format
(
event
[
'end_time'
])
)
results
.
extend
(
res
)
except
Exception
as
e
:
print
(
'ERROR:'
,
e
)
else
:
print
(
res
)
print
(
res
)
for
event
in
res
:
cur_start_time
=
max
(
event
[
'start_time'
],
start_time
)
print
(
results
)
cur_end_time
=
min
(
event
[
'end_time'
],
end_time
)
# for event in res:
print
(
cur_start_time
,
cur_end_time
)
# cur_start_time = max(event['start_time'], start_time)
# print(event)
# cur_end_time = min(event['end_time'], end_time)
file_info
,
error_log
=
stream_record
(
event
[
'stream_url'
],
cur_start_time
,
cur_end_time
)
# print(cur_start_time, cur_end_time)
print
(
file_info
)
# # print(event)
# file_info, error_log = stream_record(event['stream_url'], cur_start_time, cur_end_time)
# print(file_info)
def
stream_record
(
stream
,
start_time
,
end_time
):
def
stream_record
(
stream
,
start_time
,
end_time
):
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论