Toggle navigation
Toggle navigation
This project
Loading...
Sign in
OnePoem
/
OnePoem-Server
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
李帅
2022-04-13 18:00:41 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
1b018f304d439365aebe10f61421e2dfc6a6cdd8
1b018f30
1 parent
731b6fa9
1.ffmpeg命令微调
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
238 additions
and
30 deletions
app/Admin/Controllers/VideoTempController.php
app/Console/Commands/DevFFmpeg.php
app/Jobs/MakeVideo.php
app/Models/VideoTemp.php
app/Admin/Controllers/VideoTempController.php
View file @
1b018f3
...
...
@@ -172,22 +172,42 @@ class VideoTempController extends AdminController
$form
->
checkbox
(
'components'
,
'组件'
)
->
when
(
'every_poem'
,
function
(
Form\BlockForm
$form
)
{
$form
->
select
(
'pos_every_poem'
,
'每日位置'
)
->
options
(
VideoTemp
::
POSITION_OPTIONS
);
$form
->
number
(
'font_size_every_poem'
,
'容器宽度'
)
->
default
(
6
)
->
help
(
'范围为1-9,默认容器外边距为1/20'
);
$form
->
text
(
'text_color_every_poem'
,
'字体颜色'
)
->
default
(
'white'
);
$form
->
text
(
'text_bg_color_every_poem'
,
'背景颜色'
);
$form
->
rate
(
'opacity_every_poem'
,
'透明度'
)
->
default
(
50
)
->
help
(
'范围为0-100,100表示不透明,0表示完全透明'
);
$form
->
divider
();
})
->
when
(
'one_poem'
,
function
(
Form\BlockForm
$form
)
{
$form
->
select
(
'pos_one_poem'
,
'一言位置'
)
->
options
(
VideoTemp
::
POSITION_OPTIONS
);
$form
->
number
(
'font_size_one_poem'
,
'容器宽度'
)
->
default
(
6
)
->
help
(
'范围为1-9,默认容器外边距为1/20'
);
$form
->
text
(
'text_color_one_poem'
,
'字体颜色'
)
->
default
(
'white'
);
$form
->
text
(
'text_bg_color_one_poem'
,
'背景颜色'
);
$form
->
rate
(
'opacity_one_poem'
,
'透明度'
)
->
default
(
50
)
->
help
(
'范围为0-100,100表示不透明,0表示完全透明'
);
$form
->
divider
();
})
->
when
(
'weather'
,
function
(
Form\BlockForm
$form
)
{
$form
->
select
(
'pos_weather'
,
'天气位置'
)
->
options
(
VideoTemp
::
POSITION_OPTIONS
);
$form
->
number
(
'font_size_weather'
,
'容器宽度'
)
->
default
(
6
)
->
help
(
'范围为1-9,默认容器外边距为1/20'
);
$form
->
text
(
'text_color_weather'
,
'字体颜色'
)
->
default
(
'white'
);
$form
->
text
(
'text_bg_color_weather'
,
'背景颜色'
);
$form
->
rate
(
'opacity_weather'
,
'透明度'
)
->
default
(
50
)
->
help
(
'范围为0-100,100表示不透明,0表示完全透明'
);
$form
->
divider
();
})
->
when
(
'date'
,
function
(
Form\BlockForm
$form
)
{
$form
->
select
(
'pos_date'
,
'日期位置'
)
->
options
(
VideoTemp
::
POSITION_OPTIONS
);
$form
->
number
(
'font_size_date'
,
'容器宽度'
)
->
default
(
6
)
->
help
(
'范围为1-9,默认容器外边距为1/20'
);
$form
->
text
(
'text_color_date'
,
'字体颜色'
)
->
default
(
'white'
);
$form
->
text
(
'text_bg_color_date'
,
'背景颜色'
);
$form
->
rate
(
'opacity_date'
,
'透明度'
)
->
default
(
50
)
->
help
(
'范围为0-100,100表示不透明,0表示完全透明'
);
$form
->
divider
();
})
->
when
(
'feel'
,
function
(
Form\BlockForm
$form
)
{
$form
->
select
(
'pos_feel'
,
'有感位置'
)
->
options
(
VideoTemp
::
POSITION_OPTIONS
);
$form
->
number
(
'font_size_feel'
,
'容器宽度'
)
->
default
(
6
)
->
help
(
'范围为1-9,默认容器外边距为1/20'
);
$form
->
text
(
'text_color_feel'
,
'字体颜色'
)
->
default
(
'white'
);
$form
->
text
(
'text_bg_color_feel'
,
'背景颜色'
);
$form
->
rate
(
'opacity_feel'
,
'透明度'
)
->
default
(
50
)
->
help
(
'范围为0-100,100表示不透明,0表示完全透明'
);
$form
->
divider
();
})
->
default
([
'one_poem'
,
'weather'
,
'date'
])
...
...
@@ -230,7 +250,11 @@ class VideoTempController extends AdminController
Component
::
query
()
->
create
([
'temp_id'
=>
$vide_temp
->
id
,
'name'
=>
$component
,
'position'
=>
$all
[
'pos_'
.
$component
]
'position'
=>
$all
[
'pos_'
.
$component
],
'font_size'
=>
$all
[
'font_size_'
.
$component
],
'text_color'
=>
$all
[
'text_color_'
.
$component
],
'text_bg_color'
=>
$all
[
'text_bg_color_'
.
$component
],
'opacity'
=>
$all
[
'opacity_'
.
$component
],
]);
}
}
...
...
app/Console/Commands/DevFFmpeg.php
View file @
1b018f3
...
...
@@ -4,8 +4,11 @@ namespace App\Console\Commands;
use
App\Models\AdminMakeVideo
;
use
App\Models\Immerse
;
use
App\Models\VideoTemp
;
use
Carbon\Carbon
;
use
Illuminate\Console\Command
;
use
Illuminate\Support\Facades\Storage
;
use
voku\helper\ASCII
;
class
DevFFmpeg
extends
Command
{
...
...
@@ -52,6 +55,9 @@ class DevFFmpeg extends Command
$is_bgm
=
false
;
$bgm
=
$path
.
'bgm.aac'
;
$string
=
$this
->
getTextContentString
();
// 1.getmediainfo 记录时长,音频视频取最长。
$cmd
=
$this
->
ffprobe
.
' -v quiet -print_format json -show_format -show_streams '
.
escapeshellarg
(
$file
);
$output
=
$this
->
execmd
(
$cmd
);
...
...
@@ -158,16 +164,9 @@ class DevFFmpeg extends Command
' -i '
.
escapeshellarg
(
$path
.
'logo.png'
)
.
$audio_input
.
' -filter_complex "[0:0] '
.
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$path
.
'arialuni.ttf'
)
.
':'
.
'text='
.
escapeshellarg
(
$content
)
.
':'
.
'fontsize='
.
$font_size
.
':'
.
'fontcolor=white@1.0:'
.
'x='
.
escapeshellarg
(
'(w-text_w)/2'
)
.
':'
.
'y='
.
escapeshellarg
(
'(h-text_h)/2'
)
.
':'
.
'box=1:boxcolor=0xd0cdcc@0.5'
.
'" [text];'
.
'[text] [2:v]overlay=20:20[water];[water]'
.
$audio_filter
.
'[1:0][1:1] concat=n=2:v=1:a=1[v][a]" '
.
$string
.
'[text];[text]'
.
'[2:v]overlay=20:20[water];[water]'
.
$audio_filter
.
'[1:0][1:1] concat=n=2:v=1:a=1[v][a]" '
.
' -map [v] -map [a]'
.
' -c:v libx264 -bt 256k -r 25'
.
' -ar 44100 -ac 2 -qmin 30 -qmax 60 -profile:v baseline -preset fast '
.
...
...
@@ -737,5 +736,98 @@ class DevFFmpeg extends Command
return
false
;
}
}
public
function
getTextContentString
()
{
$components
=
VideoTemp
::
query
()
->
find
(
6
)
->
components
()
->
get
();
$font
=
Storage
::
disk
(
'public'
)
->
path
(
'ffmpeg/arialuni.ttf'
);
$drawtext
=
''
;
foreach
(
$components
as
$component
)
{
switch
(
$component
->
name
){
case
'one_poem'
:
$content
=
'题破山寺后禅院'
.
"
\t
"
.
' -- 常建'
.
PHP_EOL
.
'清晨入古寺,初日照高林。'
.
PHP_EOL
.
'曲径通幽处,禅房花木深。'
.
PHP_EOL
.
'山光悦鸟性,潭影空人心。'
.
PHP_EOL
.
'万籁此都寂,但余钟磬音。'
.
PHP_EOL
;
$text_color
=
$component
->
text_color
??
'white'
;
$text_bg_color
=
$component
->
text_bg_color
??
'0xd0cdcc'
;
$opacity
=
$component
->
opacity
?
$component
->
opacity
/
100
:
'0.5'
;
$drawtext
.=
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font
)
.
':'
.
'text='
.
escapeshellarg
(
$content
)
.
':'
.
'fontsize='
.
$component
->
font_size
.
':'
.
'fontcolor='
.
$text_color
.
'@1.0:'
.
'x='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
0
])
.
':'
.
'y='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
1
])
.
':'
.
'box=1:boxcolor='
.
$text_bg_color
.
'@'
.
$opacity
.
'", '
;
break
;
case
'every_poem'
:
break
;
case
'weather'
:
$content
=
'多云'
;
$text_color
=
$component
->
text_color
??
'white'
;
$text_bg_color
=
$component
->
text_bg_color
??
'0xd0cdcc'
;
$opacity
=
$component
->
opacity
?
$component
->
opacity
/
100
:
'0.5'
;
$drawtext
.=
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font
)
.
':'
.
'text='
.
escapeshellarg
(
$content
)
.
':'
.
'fontsize='
.
$component
->
font_size
.
':'
.
'fontcolor='
.
$text_color
.
'@1.0:'
.
'x='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
0
])
.
':'
.
'y='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
1
])
.
':'
.
'box=1:boxcolor='
.
$text_bg_color
.
'@'
.
$opacity
.
'", '
;
break
;
case
'date'
:
$content
=
Carbon
::
now
()
->
format
(
'Y年m月d日H时'
);
$text_color
=
$component
->
text_color
??
'white'
;
$text_bg_color
=
$component
->
text_bg_color
??
'0xd0cdcc'
;
$opacity
=
$component
->
opacity
?
$component
->
opacity
/
100
:
'0.5'
;
$drawtext
.=
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font
)
.
':'
.
'text='
.
escapeshellarg
(
$content
)
.
':'
.
'fontsize='
.
$component
->
font_size
.
':'
.
'fontcolor='
.
$text_color
.
'@1.0:'
.
'x='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
0
])
.
':'
.
'y='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
1
])
.
':'
.
'box=1:boxcolor='
.
$text_bg_color
.
'@'
.
$opacity
.
'", '
;
break
;
case
'feel'
:
$content
=
'测试有感文本'
;
$text_color
=
$component
->
text_color
??
'white'
;
$text_bg_color
=
$component
->
text_bg_color
??
'0xd0cdcc'
;
$opacity
=
$component
->
opacity
?
$component
->
opacity
/
100
:
'0.5'
;
$drawtext
.=
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font
)
.
':'
.
'text='
.
escapeshellarg
(
$content
)
.
':'
.
'fontsize='
.
$component
->
font_size
.
':'
.
'fontcolor='
.
$text_color
.
'@1.0:'
.
'x='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
0
])
.
':'
.
'y='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
1
])
.
':'
.
'box=1:boxcolor='
.
$text_bg_color
.
'@'
.
$opacity
.
'", '
;
break
;
}
}
return
rtrim
(
$drawtext
,
', '
);
}
}
...
...
app/Jobs/MakeVideo.php
View file @
1b018f3
...
...
@@ -4,6 +4,8 @@ namespace App\Jobs;
use
App\Models\AdminMakeVideo
;
use
App\Models\Immerse
;
use
App\Models\VideoTemp
;
use
Carbon\Carbon
;
use
Illuminate\Bus\Queueable
;
use
Illuminate\Contracts\Queue\ShouldBeUnique
;
use
Illuminate\Contracts\Queue\ShouldQueue
;
...
...
@@ -25,6 +27,8 @@ class MakeVideo implements ShouldQueue
protected
$ffplay
;
protected
$width
;
/**
* Create a new job instance.
* @param AdminMakeVideo $adminMakeVideo
...
...
@@ -114,14 +118,14 @@ class MakeVideo implements ShouldQueue
$end_wallpaper
=
Storage
::
disk
(
'public'
)
->
path
(
'ffmpeg'
)
.
"/end_wallpaper.png"
;
$thumbnail
=
Storage
::
disk
(
'public'
)
->
path
(
'ffmpeg'
)
.
"/thumbnail.png"
;
$font
=
Storage
::
disk
(
'public'
)
->
path
(
'ffmpeg'
)
.
"/arialuni.ttf"
;
$signature
=
"一言官方出品"
;
$signature
=
"一言
·
官方出品"
;
// 生成贴纸和签名
$end_wallpaper
=
$this
->
wallpaperWithSignature
(
$end_wallpaper
,
$thumbnail
,
$signature
,
$font
);
// 截取最后一帧
$last_frame_video
=
$this
->
getTempPath
();
$width
=
$media_info
[
'streams'
][
0
][
'width'
];
$
this
->
width
=
$
width
=
$media_info
[
'streams'
][
0
][
'width'
];
$height
=
$media_info
[
'streams'
][
0
][
'height'
];
$size
=
$width
.
'x'
.
$height
;
$time_length
=
0.7
;
...
...
@@ -138,12 +142,9 @@ class MakeVideo implements ShouldQueue
$signature_y
=
-
20
;
$animate
=
$this
->
makeAnimate
(
$last_frame_video
,
$end_wallpaper
,
''
,
$signature_x
,
$signature_y
,
$font
);
$font_size
=
ceil
(
$width
/
16
);
$content
=
$adminMakeVideo
->
poem
->
content
.
PHP_EOL
;
$content_position
=
$adminMakeVideo
->
getContentPosition
();
$watermark
=
Storage
::
disk
(
'public'
)
->
path
(
'ffmpeg/LOGO_eng.png'
);
$font_family
=
Storage
::
disk
(
'public'
)
->
path
(
'ffmpeg/arialuni.ttf'
);
$this
->
getTextContentString
(
$adminMakeVideo
);
$watermark
=
Storage
::
disk
(
'public'
)
->
path
(
'ffmpeg/LOGO_eng.png'
);
$video
=
$this
->
getTempPath
(
'.mp4'
,
false
);
$cmd
=
$this
->
ffmpeg
.
' -y '
.
...
...
@@ -152,15 +153,8 @@ class MakeVideo implements ShouldQueue
' -i '
.
escapeshellarg
(
$watermark
)
.
$audio_input
.
' -filter_complex "[0:0] '
.
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font_family
)
.
':'
.
'text='
.
escapeshellcmd
(
$content
)
.
':'
.
'fontsize='
.
$font_size
.
':'
.
'fontcolor=white@1.0:'
.
'x='
.
escapeshellarg
(
$content_position
[
0
])
.
':'
.
'y='
.
escapeshellarg
(
$content_position
[
1
])
.
':'
.
'box=1:boxcolor=0xd0cdcc@0.5'
.
'" [text];'
.
$this
->
getTextContentString
()
.
'[text];[text]'
.
'[text] [2:v]overlay=20:20[water];[water]'
.
$audio_filter
.
'[1:0][1:1] concat=n=2:v=1:a=1[v][a]" '
.
' -map [v] -map [a]'
.
' -c:v libx264 -bt 256k -r 25'
.
...
...
@@ -600,4 +594,102 @@ class MakeVideo implements ShouldQueue
return
false
;
}
}
public
function
getTextContentString
()
{
$components
=
$this
->
adminMakeVideo
->
temp
->
components
->
get
();
$font
=
Storage
::
disk
(
'public'
)
->
path
(
'ffmpeg/arialuni.ttf'
);
$drawtext
=
''
;
foreach
(
$components
as
$component
)
{
switch
(
$component
->
name
){
case
'one_poem'
:
$content
=
$this
->
adminMakeVideo
->
poem
->
content
.
PHP_EOL
;
$text_color
=
$component
->
text_color
??
'white'
;
$text_bg_color
=
$component
->
text_bg_color
??
'0xd0cdcc'
;
$opacity
=
$component
->
opacity
?
$component
->
opacity
/
100
:
'0.5'
;
$drawtext
.=
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font
)
.
':'
.
'text='
.
escapeshellcmd
(
$content
)
.
':'
.
'fontsize='
.
$this
->
calcFontSize
(
$component
->
font_size
,
$content
)
.
':'
.
'fontcolor='
.
$text_color
.
'@1.0:'
.
'x='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
0
])
.
':'
.
'y='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
1
])
.
':'
.
'box=1:boxcolor='
.
$text_bg_color
.
'@'
.
$opacity
.
'", '
;
break
;
case
'every_poem'
:
break
;
case
'weather'
:
$content
=
'多云'
;
$text_color
=
$component
->
text_color
??
'white'
;
$text_bg_color
=
$component
->
text_bg_color
??
'0xd0cdcc'
;
$opacity
=
$component
->
opacity
?
$component
->
opacity
/
100
:
'0.5'
;
$drawtext
.=
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font
)
.
':'
.
'text='
.
escapeshellarg
(
$content
)
.
':'
.
'fontsize='
.
$this
->
calcFontSize
(
$component
->
font_size
,
$content
)
.
':'
.
'fontcolor='
.
$text_color
.
'@1.0:'
.
'x='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
0
])
.
':'
.
'y='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
1
])
.
':'
.
'box=1:boxcolor='
.
$text_bg_color
.
'@'
.
$opacity
.
'", '
;
break
;
case
'date'
:
$content
=
Carbon
::
now
()
->
format
(
'Y年m月d日H时'
);
$text_color
=
$component
->
text_color
??
'white'
;
$text_bg_color
=
$component
->
text_bg_color
??
'0xd0cdcc'
;
$opacity
=
$component
->
opacity
?
$component
->
opacity
/
100
:
'0.5'
;
$drawtext
.=
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font
)
.
':'
.
'text='
.
escapeshellarg
(
$content
)
.
':'
.
'fontsize='
.
$this
->
calcFontSize
(
$component
->
font_size
,
$content
)
.
':'
.
'fontcolor='
.
$text_color
.
'@1.0:'
.
'x='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
0
])
.
':'
.
'y='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
1
])
.
':'
.
'box=1:boxcolor='
.
$text_bg_color
.
'@'
.
$opacity
.
'", '
;
break
;
case
'feel'
:
$content
=
$this
->
adminMakeVideo
->
feel
;
$text_color
=
$component
->
text_color
??
'white'
;
$text_bg_color
=
$component
->
text_bg_color
??
'0xd0cdcc'
;
$opacity
=
$component
->
opacity
?
$component
->
opacity
/
100
:
'0.5'
;
$drawtext
.=
'drawtext="'
.
'fontfile='
.
escapeshellarg
(
$font
)
.
':'
.
'text='
.
escapeshellarg
(
$content
)
.
':'
.
'fontsize='
.
$this
->
calcFontSize
(
$component
->
font_size
,
$content
)
.
':'
.
'fontcolor='
.
$text_color
.
'@1.0:'
.
'x='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
0
])
.
':'
.
'y='
.
escapeshellarg
(
VideoTemp
::
POSITION_FFMPEG
[
$component
->
position
][
1
])
.
':'
.
'box=1:boxcolor='
.
$text_bg_color
.
'@'
.
$opacity
.
'", '
;
break
;
}
}
return
rtrim
(
$drawtext
,
', '
);
}
/**
* @param $width
* @param $content
* @return float
*/
public
function
calcFontSize
(
$width
,
$content
)
{
$max_len
=
1
;
foreach
(
explode
(
"
\n
"
,
$content
)
as
$item
){
if
(
mb_strlen
(
$item
)
>
$max_len
){
$max_len
=
mb_strlen
(
$item
);
}
}
return
ceil
(
$this
->
width
*
$width
/
10
/
$max_len
);
}
}
...
...
app/Models/VideoTemp.php
View file @
1b018f3
...
...
@@ -17,9 +17,9 @@ class VideoTemp extends Model
];
const
POSITION_FFMPEG
=
[
'topLeft'
=>
[
0
,
0
],
'topMiddle'
=>
[
'(w-text_w)/2'
,
0
],
'topRight'
=>
[
'w-text_w'
,
0
],
'midLeft'
=>
[
0
,
'(h-text_h)/2'
],
'midMiddle'
=>
[
'(w-text_w)/2'
,
'(h-text_h)/2'
],
'midRight'
=>
[
'w-text_w'
,
'(h-text_h)/2'
],
'botLeft'
=>
[
0
,
'h-text_h'
],
'botMiddle'
=>
[
'(w-text_w)/2'
,
'h-text_h'
],
'botRight'
=>
[
'w-text_w'
,
'h-text_h
'
],
'topLeft'
=>
[
'0'
,
'text_h'
],
'topMiddle'
=>
[
'(w-text_w)/2'
,
'text_h'
],
'topRight'
=>
[
'w-text_w'
,
'text_h'
],
'midLeft'
=>
[
'0'
,
'(h-text_h)/2'
],
'midMiddle'
=>
[
'(w-text_w)/2'
,
'(h-text_h)/2'
],
'midRight'
=>
[
'w-text_w'
,
'(h-text_h)/2'
],
'botLeft'
=>
[
'0'
,
'h-text_h*2'
],
'botMiddle'
=>
[
'(w-text_w)/2'
,
'h-text_h*2'
],
'botRight'
=>
[
'w-text_w'
,
'h-text_h*2
'
],
];
protected
$table
=
'video_temp'
;
...
...
Please
register
or
login
to post a comment