Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
63f22ee6
Commit
63f22ee6
authored
Feb 24, 2022
by
ziyue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
截图失败时,返回ffmpeg日志; ffmpeg命令支持相对路径
parent
a3d696d8
隐藏空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
46 行增加
和
25 行删除
+46
-25
server/FFmpegSource.cpp
+22
-16
server/FFmpegSource.h
+3
-1
server/Process.cpp
+5
-1
server/Process.h
+1
-1
server/WebApi.cpp
+15
-6
没有找到文件。
server/FFmpegSource.cpp
查看文件 @
63f22ee6
...
...
@@ -91,8 +91,9 @@ void FFmpegSource::play(const string &ffmpeg_cmd_key, const string &src_url,cons
}
char
cmd
[
1024
]
=
{
0
};
snprintf
(
cmd
,
sizeof
(
cmd
),
ffmpeg_cmd
.
data
(),
ffmpeg_bin
.
data
(),
src_url
.
data
(),
dst_url
.
data
());
_process
.
run
(
cmd
,
ffmpeg_log
.
empty
()
?
""
:
File
::
absolutePath
(
""
,
ffmpeg_log
));
snprintf
(
cmd
,
sizeof
(
cmd
),
ffmpeg_cmd
.
data
(),
File
::
absolutePath
(
""
,
ffmpeg_bin
).
data
(),
src_url
.
data
(),
dst_url
.
data
());
auto
log_file
=
ffmpeg_log
.
empty
()
?
""
:
File
::
absolutePath
(
""
,
ffmpeg_log
);
_process
.
run
(
cmd
,
log_file
);
InfoL
<<
cmd
;
if
(
is_local_ip
(
_media_info
.
_host
))
{
...
...
@@ -312,7 +313,7 @@ void FFmpegSource::onGetMediaSource(const MediaSource::Ptr &src) {
}
}
void
FFmpegSnap
::
makeSnap
(
const
string
&
play_url
,
const
string
&
save_path
,
float
timeout_sec
,
const
function
<
void
(
bool
)
>
&
cb
)
{
void
FFmpegSnap
::
makeSnap
(
const
string
&
play_url
,
const
string
&
save_path
,
float
timeout_sec
,
const
onSnap
&
cb
)
{
GET_CONFIG
(
string
,
ffmpeg_bin
,
FFmpeg
::
kBin
);
GET_CONFIG
(
string
,
ffmpeg_snap
,
FFmpeg
::
kSnap
);
GET_CONFIG
(
string
,
ffmpeg_log
,
FFmpeg
::
kLog
);
...
...
@@ -321,28 +322,33 @@ void FFmpegSnap::makeSnap(const string &play_url, const string &save_path, float
auto
elapsed_ms
=
ticker
.
elapsedTime
();
if
(
elapsed_ms
>
timeout_sec
*
1000
)
{
//超时,后台线程负载太高,当代太久才启动该任务
cb
(
false
);
cb
(
false
,
"wait work poller schedule snap task timeout"
);
return
;
}
char
cmd
[
1024
]
=
{
0
};
snprintf
(
cmd
,
sizeof
(
cmd
),
ffmpeg_snap
.
data
(),
ffmpeg_bin
.
data
(),
play_url
.
data
(),
save_path
.
data
());
char
cmd
[
2048
]
=
{
0
};
snprintf
(
cmd
,
sizeof
(
cmd
),
ffmpeg_snap
.
data
(),
File
::
absolutePath
(
""
,
ffmpeg_bin
).
data
(),
play_url
.
data
(),
save_path
.
data
());
std
::
shared_ptr
<
Process
>
process
=
std
::
make_shared
<
Process
>
();
process
->
run
(
cmd
,
ffmpeg_log
.
empty
()
?
""
:
File
::
absolutePath
(
""
,
ffmpeg_log
));
auto
log_file
=
ffmpeg_log
.
empty
()
?
ffmpeg_log
:
File
::
absolutePath
(
""
,
ffmpeg_log
);
process
->
run
(
cmd
,
log_file
);
//定时器延时应该减去后台任务启动的延时
auto
delayTask
=
EventPollerPool
::
Instance
().
getPoller
()
->
doDelayTask
((
uint64_t
)(
timeout_sec
*
1000
-
elapsed_ms
),[
process
,
cb
](){
if
(
process
->
wait
(
false
)){
//FFmpeg进程还在运行,超时就关闭它
process
->
kill
(
2000
);
}
return
0
;
});
auto
delayTask
=
EventPollerPool
::
Instance
().
getPoller
()
->
doDelayTask
(
(
uint64_t
)(
timeout_sec
*
1000
-
elapsed_ms
),
[
process
,
cb
,
log_file
,
save_path
]()
{
if
(
process
->
wait
(
false
))
{
// FFmpeg进程还在运行,超时就关闭它
process
->
kill
(
2000
);
}
return
0
;
});
//等待FFmpeg进程退出
process
->
wait
(
true
);
//FFmpeg进程退出了可以取消定时器了
//
FFmpeg进程退出了可以取消定时器了
delayTask
->
cancel
();
//执行回调函数
cb
(
process
->
exit_code
()
==
0
);
bool
success
=
process
->
exit_code
()
==
0
&&
File
::
fileSize
(
save_path
.
data
());
cb
(
success
,
(
!
success
&&
!
log_file
.
empty
())
?
File
::
loadFile
(
log_file
.
data
())
:
""
);
});
}
server/FFmpegSource.h
查看文件 @
63f22ee6
...
...
@@ -25,12 +25,14 @@ namespace FFmpeg {
class
FFmpegSnap
{
public
:
using
onSnap
=
std
::
function
<
void
(
bool
success
,
const
std
::
string
&
err_msg
)
>
;
/// 创建截图
/// \param play_url 播放url地址,只要FFmpeg支持即可
/// \param save_path 截图jpeg文件保存路径
/// \param timeout_sec 生成截图超时时间(防止阻塞太久)
/// \param cb 生成截图成功与否回调
static
void
makeSnap
(
const
std
::
string
&
play_url
,
const
std
::
string
&
save_path
,
float
timeout_sec
,
const
std
::
function
<
void
(
bool
)
>
&
cb
);
static
void
makeSnap
(
const
std
::
string
&
play_url
,
const
std
::
string
&
save_path
,
float
timeout_sec
,
const
onSnap
&
cb
);
private
:
FFmpegSnap
()
=
delete
;
~
FFmpegSnap
()
=
delete
;
...
...
server/Process.cpp
查看文件 @
63f22ee6
...
...
@@ -30,7 +30,7 @@
using
namespace
toolkit
;
using
namespace
std
;
void
Process
::
run
(
const
string
&
cmd
,
const
string
&
log_file_tmp
)
{
void
Process
::
run
(
const
string
&
cmd
,
string
&
log_file_tmp
)
{
kill
(
2000
);
#ifdef _WIN32
STARTUPINFO
si
=
{
0
};
...
...
@@ -42,6 +42,7 @@ void Process::run(const string &cmd, const string &log_file_tmp) {
}
else
{
log_file
=
StrPrinter
<<
log_file_tmp
<<
"."
<<
getCurrentMillisecond
();
}
log_file_tmp
=
log_file
;
//重定向shell日志至文件
auto
fp
=
File
::
create_file
(
log_file
.
data
(),
"ab"
);
...
...
@@ -92,6 +93,8 @@ void Process::run(const string &cmd, const string &log_file_tmp) {
//在启动子进程时,暂时禁用SIGINT、SIGTERM信号
signal
(
SIGINT
,
SIG_IGN
);
signal
(
SIGTERM
,
SIG_IGN
);
signal
(
SIGSEGV
,
SIG_IGN
);
signal
(
SIGABRT
,
SIG_IGN
);
//重定向shell日志至文件
auto
fp
=
File
::
create_file
(
log_file
.
data
(),
"ab"
);
...
...
@@ -148,6 +151,7 @@ void Process::run(const string &cmd, const string &log_file_tmp) {
}
else
{
log_file
=
StrPrinter
<<
log_file_tmp
<<
"."
<<
_pid
;
}
log_file_tmp
=
log_file
;
InfoL
<<
"start child process "
<<
_pid
<<
", log file:"
<<
log_file
;
#endif // _WIN32
}
...
...
server/Process.h
查看文件 @
63f22ee6
...
...
@@ -24,7 +24,7 @@ class Process {
public
:
Process
();
~
Process
();
void
run
(
const
std
::
string
&
cmd
,
const
std
::
string
&
log_file
);
void
run
(
const
std
::
string
&
cmd
,
std
::
string
&
log_file
);
void
kill
(
int
max_delay
,
bool
force
=
false
);
bool
wait
(
bool
block
=
true
);
int
exit_code
();
...
...
server/WebApi.cpp
查看文件 @
63f22ee6
...
...
@@ -1251,14 +1251,23 @@ void installWebApi() {
static
auto
responseSnap
=
[](
const
string
&
snap_path
,
const
HttpSession
::
KeyValue
&
headerIn
,
const
HttpSession
::
HttpResponseInvoker
&
invoker
)
{
const
HttpSession
::
HttpResponseInvoker
&
invoker
,
const
string
&
err_msg
=
""
)
{
static
bool
s_snap_success_once
=
false
;
StrCaseMap
headerOut
;
GET_CONFIG
(
string
,
defaultSnap
,
API
::
kDefaultSnap
);
if
(
!
File
::
fileSize
(
snap_path
.
data
())
&&
!
defaultSnap
.
empty
())
{
//空文件且设置了预设图,则返回预设图片(也就是FFmpeg生成截图中空档期的默认图片)
const_cast
<
string
&>
(
snap_path
)
=
File
::
absolutePath
(
defaultSnap
,
""
);
if
(
!
File
::
fileSize
(
snap_path
.
data
()))
{
if
(
!
err_msg
.
empty
()
&&
(
!
s_snap_success_once
||
defaultSnap
.
empty
()))
{
//重来没截图成功过或者默认截图图片为空,那么直接返回FFmpeg错误日志
headerOut
[
"Content-Type"
]
=
HttpFileManager
::
getContentType
(
".txt"
);
invoker
.
responseFile
(
headerIn
,
headerOut
,
err_msg
,
false
,
false
);
return
;
}
//截图成功过一次,那么认为配置无错误,截图失败时,返回预设默认图片
const_cast
<
string
&>
(
snap_path
)
=
File
::
absolutePath
(
""
,
defaultSnap
);
headerOut
[
"Content-Type"
]
=
HttpFileManager
::
getContentType
(
snap_path
.
data
());
}
else
{
s_snap_success_once
=
true
;
//之前生成的截图文件,我们默认为jpeg格式
headerOut
[
"Content-Type"
]
=
HttpFileManager
::
getContentType
(
".jpeg"
);
}
...
...
@@ -1317,7 +1326,7 @@ void installWebApi() {
//启动FFmpeg进程,开始截图,生成临时文件,截图成功后替换为正式文件
auto
new_snap_tmp
=
new_snap
+
".tmp"
;
FFmpegSnap
::
makeSnap
(
allArgs
[
"url"
],
new_snap_tmp
,
allArgs
[
"timeout_sec"
],
[
invoker
,
allArgs
,
new_snap
,
new_snap_tmp
](
bool
success
)
{
FFmpegSnap
::
makeSnap
(
allArgs
[
"url"
],
new_snap_tmp
,
allArgs
[
"timeout_sec"
],
[
invoker
,
allArgs
,
new_snap
,
new_snap_tmp
](
bool
success
,
const
string
&
err_msg
)
{
if
(
!
success
)
{
//生成截图失败,可能残留空文件
File
::
delete_file
(
new_snap_tmp
.
data
());
...
...
@@ -1326,7 +1335,7 @@ void installWebApi() {
File
::
delete_file
(
new_snap
.
data
());
rename
(
new_snap_tmp
.
data
(),
new_snap
.
data
());
}
responseSnap
(
new_snap
,
allArgs
.
getParser
().
getHeader
(),
invoker
);
responseSnap
(
new_snap
,
allArgs
.
getParser
().
getHeader
(),
invoker
,
err_msg
);
});
});
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论