李帅

1.ffmpeg命令微调

...@@ -172,22 +172,42 @@ class VideoTempController extends AdminController ...@@ -172,22 +172,42 @@ class VideoTempController extends AdminController
172 $form->checkbox('components','组件') 172 $form->checkbox('components','组件')
173 ->when('every_poem', function (Form\BlockForm $form) { 173 ->when('every_poem', function (Form\BlockForm $form) {
174 $form->select('pos_every_poem', '每日位置')->options(VideoTemp::POSITION_OPTIONS); 174 $form->select('pos_every_poem', '每日位置')->options(VideoTemp::POSITION_OPTIONS);
175 + $form->number('font_size_every_poem','容器宽度')->default(6)->help('范围为1-9,默认容器外边距为1/20');
176 + $form->text('text_color_every_poem','字体颜色')->default('white');
177 + $form->text('text_bg_color_every_poem','背景颜色');
178 + $form->rate('opacity_every_poem','透明度')->default(50)->help('范围为0-100,100表示不透明,0表示完全透明');
175 $form->divider(); 179 $form->divider();
176 }) 180 })
177 ->when('one_poem', function (Form\BlockForm $form) { 181 ->when('one_poem', function (Form\BlockForm $form) {
178 $form->select('pos_one_poem', '一言位置')->options(VideoTemp::POSITION_OPTIONS); 182 $form->select('pos_one_poem', '一言位置')->options(VideoTemp::POSITION_OPTIONS);
183 + $form->number('font_size_one_poem','容器宽度')->default(6)->help('范围为1-9,默认容器外边距为1/20');
184 + $form->text('text_color_one_poem','字体颜色')->default('white');
185 + $form->text('text_bg_color_one_poem','背景颜色');
186 + $form->rate('opacity_one_poem','透明度')->default(50)->help('范围为0-100,100表示不透明,0表示完全透明');
179 $form->divider(); 187 $form->divider();
180 }) 188 })
181 ->when('weather', function (Form\BlockForm $form) { 189 ->when('weather', function (Form\BlockForm $form) {
182 $form->select('pos_weather', '天气位置')->options(VideoTemp::POSITION_OPTIONS); 190 $form->select('pos_weather', '天气位置')->options(VideoTemp::POSITION_OPTIONS);
191 + $form->number('font_size_weather','容器宽度')->default(6)->help('范围为1-9,默认容器外边距为1/20');
192 + $form->text('text_color_weather','字体颜色')->default('white');
193 + $form->text('text_bg_color_weather','背景颜色');
194 + $form->rate('opacity_weather','透明度')->default(50)->help('范围为0-100,100表示不透明,0表示完全透明');
183 $form->divider(); 195 $form->divider();
184 }) 196 })
185 ->when('date', function (Form\BlockForm $form) { 197 ->when('date', function (Form\BlockForm $form) {
186 $form->select('pos_date', '日期位置')->options(VideoTemp::POSITION_OPTIONS); 198 $form->select('pos_date', '日期位置')->options(VideoTemp::POSITION_OPTIONS);
199 + $form->number('font_size_date','容器宽度')->default(6)->help('范围为1-9,默认容器外边距为1/20');
200 + $form->text('text_color_date','字体颜色')->default('white');
201 + $form->text('text_bg_color_date','背景颜色');
202 + $form->rate('opacity_date','透明度')->default(50)->help('范围为0-100,100表示不透明,0表示完全透明');
187 $form->divider(); 203 $form->divider();
188 }) 204 })
189 ->when('feel', function (Form\BlockForm $form) { 205 ->when('feel', function (Form\BlockForm $form) {
190 $form->select('pos_feel', '有感位置')->options(VideoTemp::POSITION_OPTIONS); 206 $form->select('pos_feel', '有感位置')->options(VideoTemp::POSITION_OPTIONS);
207 + $form->number('font_size_feel','容器宽度')->default(6)->help('范围为1-9,默认容器外边距为1/20');
208 + $form->text('text_color_feel','字体颜色')->default('white');
209 + $form->text('text_bg_color_feel','背景颜色');
210 + $form->rate('opacity_feel','透明度')->default(50)->help('范围为0-100,100表示不透明,0表示完全透明');
191 $form->divider(); 211 $form->divider();
192 }) 212 })
193 ->default(['one_poem','weather','date']) 213 ->default(['one_poem','weather','date'])
...@@ -230,7 +250,11 @@ class VideoTempController extends AdminController ...@@ -230,7 +250,11 @@ class VideoTempController extends AdminController
230 Component::query()->create([ 250 Component::query()->create([
231 'temp_id' => $vide_temp->id, 251 'temp_id' => $vide_temp->id,
232 'name' => $component, 252 'name' => $component,
233 - 'position' => $all['pos_' . $component] 253 + 'position' => $all['pos_' . $component],
254 + 'font_size' => $all['font_size_' . $component],
255 + 'text_color' => $all['text_color_' . $component],
256 + 'text_bg_color' => $all['text_bg_color_' . $component],
257 + 'opacity' => $all['opacity_' . $component],
234 ]); 258 ]);
235 } 259 }
236 } 260 }
......
...@@ -4,8 +4,11 @@ namespace App\Console\Commands; ...@@ -4,8 +4,11 @@ namespace App\Console\Commands;
4 4
5 use App\Models\AdminMakeVideo; 5 use App\Models\AdminMakeVideo;
6 use App\Models\Immerse; 6 use App\Models\Immerse;
7 +use App\Models\VideoTemp;
8 +use Carbon\Carbon;
7 use Illuminate\Console\Command; 9 use Illuminate\Console\Command;
8 use Illuminate\Support\Facades\Storage; 10 use Illuminate\Support\Facades\Storage;
11 +use voku\helper\ASCII;
9 12
10 class DevFFmpeg extends Command 13 class DevFFmpeg extends Command
11 { 14 {
...@@ -52,6 +55,9 @@ class DevFFmpeg extends Command ...@@ -52,6 +55,9 @@ class DevFFmpeg extends Command
52 $is_bgm = false; 55 $is_bgm = false;
53 $bgm = $path . 'bgm.aac'; 56 $bgm = $path . 'bgm.aac';
54 57
58 +
59 + $string = $this->getTextContentString();
60 +
55 // 1.getmediainfo 记录时长,音频视频取最长。 61 // 1.getmediainfo 记录时长,音频视频取最长。
56 $cmd = $this->ffprobe . ' -v quiet -print_format json -show_format -show_streams ' . escapeshellarg($file); 62 $cmd = $this->ffprobe . ' -v quiet -print_format json -show_format -show_streams ' . escapeshellarg($file);
57 $output = $this->execmd($cmd); 63 $output = $this->execmd($cmd);
...@@ -158,16 +164,9 @@ class DevFFmpeg extends Command ...@@ -158,16 +164,9 @@ class DevFFmpeg extends Command
158 ' -i ' . escapeshellarg($path . 'logo.png'). 164 ' -i ' . escapeshellarg($path . 'logo.png').
159 $audio_input. 165 $audio_input.
160 ' -filter_complex "[0:0] ' . 166 ' -filter_complex "[0:0] ' .
161 - 'drawtext="'. 167 + $string.
162 - 'fontfile=' . escapeshellarg($path . 'arialuni.ttf') . ':' . 168 + '[text];[text]'.
163 - 'text=' . escapeshellarg($content) . ':'. 169 + '[2:v]overlay=20:20[water];[water]'.$audio_filter.'[1:0][1:1] concat=n=2:v=1:a=1[v][a]" '.
164 - 'fontsize='.$font_size.':'.
165 - 'fontcolor=white@1.0:'.
166 - 'x=' . escapeshellarg('(w-text_w)/2') . ':' .
167 - 'y=' . escapeshellarg('(h-text_h)/2') . ':' .
168 - 'box=1:boxcolor=0xd0cdcc@0.5'.
169 - '" [text];'.
170 - '[text] [2:v]overlay=20:20[water];[water]'.$audio_filter.'[1:0][1:1] concat=n=2:v=1:a=1[v][a]" '.
171 ' -map [v] -map [a]'. 170 ' -map [v] -map [a]'.
172 ' -c:v libx264 -bt 256k -r 25' . 171 ' -c:v libx264 -bt 256k -r 25' .
173 ' -ar 44100 -ac 2 -qmin 30 -qmax 60 -profile:v baseline -preset fast ' . 172 ' -ar 44100 -ac 2 -qmin 30 -qmax 60 -profile:v baseline -preset fast ' .
...@@ -737,5 +736,98 @@ class DevFFmpeg extends Command ...@@ -737,5 +736,98 @@ class DevFFmpeg extends Command
737 return false; 736 return false;
738 } 737 }
739 } 738 }
739 +
740 + public function getTextContentString()
741 + {
742 + $components = VideoTemp::query()->find(6)->components()->get();
743 +
744 + $font = Storage::disk('public')->path('ffmpeg/arialuni.ttf');
745 +
746 + $drawtext = '';
747 +
748 + foreach ($components as $component) {
749 + switch ($component->name){
750 + case 'one_poem':
751 + $content = '题破山寺后禅院' . "\t" . ' -- 常建' . PHP_EOL .
752 + '清晨入古寺,初日照高林。' . PHP_EOL .
753 + '曲径通幽处,禅房花木深。' . PHP_EOL .
754 + '山光悦鸟性,潭影空人心。' . PHP_EOL .
755 + '万籁此都寂,但余钟磬音。' . PHP_EOL ;
756 +
757 + $text_color = $component->text_color ?? 'white';
758 + $text_bg_color = $component->text_bg_color ?? '0xd0cdcc';
759 + $opacity = $component->opacity ? $component->opacity / 100 : '0.5';
760 +
761 + $drawtext .= 'drawtext="'.
762 + 'fontfile=' . escapeshellarg($font) . ':' .
763 + 'text=' . escapeshellarg($content) . ':' .
764 + 'fontsize=' . $component->font_size . ':' .
765 + 'fontcolor=' . $text_color . '@1.0:' .
766 + 'x=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][0]) . ':' .
767 + 'y=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][1]) . ':' .
768 + 'box=1:boxcolor=' . $text_bg_color . '@' . $opacity . '", ';
769 +
770 + break;
771 + case 'every_poem':
772 + break;
773 + case 'weather':
774 + $content = '多云';
775 + $text_color = $component->text_color ?? 'white';
776 + $text_bg_color = $component->text_bg_color ?? '0xd0cdcc';
777 + $opacity = $component->opacity ? $component->opacity / 100 : '0.5';
778 +
779 + $drawtext .= 'drawtext="'.
780 + 'fontfile=' . escapeshellarg($font) . ':' .
781 + 'text=' . escapeshellarg($content) . ':' .
782 + 'fontsize=' . $component->font_size . ':' .
783 + 'fontcolor=' . $text_color . '@1.0:' .
784 + 'x=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][0]) . ':' .
785 + 'y=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][1]) . ':' .
786 + 'box=1:boxcolor=' . $text_bg_color . '@' . $opacity . '", ';
787 +
788 + break;
789 + case 'date':
790 + $content = Carbon::now()->format('Y年m月d日H时');
791 + $text_color = $component->text_color ?? 'white';
792 + $text_bg_color = $component->text_bg_color ?? '0xd0cdcc';
793 + $opacity = $component->opacity ? $component->opacity / 100 : '0.5';
794 +
795 + $drawtext .= 'drawtext="'.
796 + 'fontfile=' . escapeshellarg($font) . ':' .
797 + 'text=' . escapeshellarg($content) . ':' .
798 + 'fontsize=' . $component->font_size . ':' .
799 + 'fontcolor=' . $text_color . '@1.0:' .
800 + 'x=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][0]) . ':' .
801 + 'y=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][1]) . ':' .
802 + 'box=1:boxcolor=' . $text_bg_color . '@' . $opacity . '", ';
803 + break;
804 + case 'feel':
805 + $content = '测试有感文本';
806 + $text_color = $component->text_color ?? 'white';
807 + $text_bg_color = $component->text_bg_color ?? '0xd0cdcc';
808 + $opacity = $component->opacity ? $component->opacity / 100 : '0.5';
809 +
810 + $drawtext .= 'drawtext="'.
811 + 'fontfile=' . escapeshellarg($font) . ':' .
812 + 'text=' . escapeshellarg($content) . ':' .
813 + 'fontsize=' . $component->font_size . ':' .
814 + 'fontcolor=' . $text_color . '@1.0:' .
815 + 'x=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][0]) . ':' .
816 + 'y=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][1]) . ':' .
817 + 'box=1:boxcolor=' . $text_bg_color . '@' . $opacity . '", ';
818 + break;
819 + }
820 + }
821 +
822 + return rtrim($drawtext,', ');
823 + }
740 } 824 }
741 825
826 +
827 +
828 +
829 +
830 +
831 +
832 +
833 +
......
...@@ -4,6 +4,8 @@ namespace App\Jobs; ...@@ -4,6 +4,8 @@ namespace App\Jobs;
4 4
5 use App\Models\AdminMakeVideo; 5 use App\Models\AdminMakeVideo;
6 use App\Models\Immerse; 6 use App\Models\Immerse;
7 +use App\Models\VideoTemp;
8 +use Carbon\Carbon;
7 use Illuminate\Bus\Queueable; 9 use Illuminate\Bus\Queueable;
8 use Illuminate\Contracts\Queue\ShouldBeUnique; 10 use Illuminate\Contracts\Queue\ShouldBeUnique;
9 use Illuminate\Contracts\Queue\ShouldQueue; 11 use Illuminate\Contracts\Queue\ShouldQueue;
...@@ -25,6 +27,8 @@ class MakeVideo implements ShouldQueue ...@@ -25,6 +27,8 @@ class MakeVideo implements ShouldQueue
25 27
26 protected $ffplay; 28 protected $ffplay;
27 29
30 + protected $width;
31 +
28 /** 32 /**
29 * Create a new job instance. 33 * Create a new job instance.
30 * @param AdminMakeVideo $adminMakeVideo 34 * @param AdminMakeVideo $adminMakeVideo
...@@ -114,14 +118,14 @@ class MakeVideo implements ShouldQueue ...@@ -114,14 +118,14 @@ class MakeVideo implements ShouldQueue
114 $end_wallpaper = Storage::disk('public')->path('ffmpeg') . "/end_wallpaper.png"; 118 $end_wallpaper = Storage::disk('public')->path('ffmpeg') . "/end_wallpaper.png";
115 $thumbnail = Storage::disk('public')->path('ffmpeg') . "/thumbnail.png"; 119 $thumbnail = Storage::disk('public')->path('ffmpeg') . "/thumbnail.png";
116 $font = Storage::disk('public')->path('ffmpeg') . "/arialuni.ttf"; 120 $font = Storage::disk('public')->path('ffmpeg') . "/arialuni.ttf";
117 - $signature = "一言官方出品"; 121 + $signature = "一言 · 官方出品";
118 122
119 // 生成贴纸和签名 123 // 生成贴纸和签名
120 $end_wallpaper = $this->wallpaperWithSignature($end_wallpaper, $thumbnail, $signature, $font); 124 $end_wallpaper = $this->wallpaperWithSignature($end_wallpaper, $thumbnail, $signature, $font);
121 125
122 // 截取最后一帧 126 // 截取最后一帧
123 $last_frame_video = $this->getTempPath(); 127 $last_frame_video = $this->getTempPath();
124 - $width = $media_info['streams'][0]['width']; 128 + $this->width = $width = $media_info['streams'][0]['width'];
125 $height = $media_info['streams'][0]['height']; 129 $height = $media_info['streams'][0]['height'];
126 $size = $width . 'x' . $height; 130 $size = $width . 'x' . $height;
127 $time_length = 0.7; 131 $time_length = 0.7;
...@@ -138,12 +142,9 @@ class MakeVideo implements ShouldQueue ...@@ -138,12 +142,9 @@ class MakeVideo implements ShouldQueue
138 $signature_y = -20; 142 $signature_y = -20;
139 $animate = $this->makeAnimate($last_frame_video, $end_wallpaper, '', $signature_x, $signature_y, $font); 143 $animate = $this->makeAnimate($last_frame_video, $end_wallpaper, '', $signature_x, $signature_y, $font);
140 144
141 - $font_size = ceil($width / 16); 145 + $this->getTextContentString($adminMakeVideo);
142 - $content = $adminMakeVideo->poem->content . PHP_EOL;
143 - $content_position = $adminMakeVideo->getContentPosition();
144 - $watermark = Storage::disk('public')->path('ffmpeg/LOGO_eng.png');
145 - $font_family = Storage::disk('public')->path('ffmpeg/arialuni.ttf');
146 146
147 + $watermark = Storage::disk('public')->path('ffmpeg/LOGO_eng.png');
147 148
148 $video = $this->getTempPath('.mp4',false); 149 $video = $this->getTempPath('.mp4',false);
149 $cmd = $this->ffmpeg . ' -y '. 150 $cmd = $this->ffmpeg . ' -y '.
...@@ -152,15 +153,8 @@ class MakeVideo implements ShouldQueue ...@@ -152,15 +153,8 @@ class MakeVideo implements ShouldQueue
152 ' -i ' . escapeshellarg($watermark). 153 ' -i ' . escapeshellarg($watermark).
153 $audio_input . 154 $audio_input .
154 ' -filter_complex "[0:0] ' . 155 ' -filter_complex "[0:0] ' .
155 - 'drawtext="'. 156 + $this->getTextContentString().
156 - 'fontfile=' . escapeshellarg($font_family) . ':' . 157 + '[text];[text]'.
157 - 'text=' . escapeshellcmd($content) . ':'.
158 - 'fontsize='.$font_size.':'.
159 - 'fontcolor=white@1.0:'.
160 - 'x=' . escapeshellarg($content_position[0]) . ':' .
161 - 'y=' . escapeshellarg($content_position[1]) . ':' .
162 - 'box=1:boxcolor=0xd0cdcc@0.5'.
163 - '" [text];'.
164 '[text] [2:v]overlay=20:20[water];[water]' . $audio_filter . '[1:0][1:1] concat=n=2:v=1:a=1[v][a]" ' . 158 '[text] [2:v]overlay=20:20[water];[water]' . $audio_filter . '[1:0][1:1] concat=n=2:v=1:a=1[v][a]" ' .
165 ' -map [v] -map [a]'. 159 ' -map [v] -map [a]'.
166 ' -c:v libx264 -bt 256k -r 25' . 160 ' -c:v libx264 -bt 256k -r 25' .
...@@ -600,4 +594,102 @@ class MakeVideo implements ShouldQueue ...@@ -600,4 +594,102 @@ class MakeVideo implements ShouldQueue
600 return false; 594 return false;
601 } 595 }
602 } 596 }
597 +
598 + public function getTextContentString()
599 + {
600 + $components = $this->adminMakeVideo->temp->components->get();
601 +
602 + $font = Storage::disk('public')->path('ffmpeg/arialuni.ttf');
603 +
604 + $drawtext = '';
605 +
606 + foreach ($components as $component) {
607 + switch ($component->name){
608 + case 'one_poem':
609 + $content = $this->adminMakeVideo->poem->content . PHP_EOL;
610 +
611 + $text_color = $component->text_color ?? 'white';
612 + $text_bg_color = $component->text_bg_color ?? '0xd0cdcc';
613 + $opacity = $component->opacity ? $component->opacity / 100 : '0.5';
614 +
615 + $drawtext .= 'drawtext="'.
616 + 'fontfile=' . escapeshellarg($font) . ':' .
617 + 'text=' . escapeshellcmd($content) . ':' .
618 + 'fontsize=' . $this->calcFontSize($component->font_size,$content) . ':' .
619 + 'fontcolor=' . $text_color . '@1.0:' .
620 + 'x=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][0]) . ':' .
621 + 'y=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][1]) . ':' .
622 + 'box=1:boxcolor=' . $text_bg_color . '@' . $opacity . '", ';
623 +
624 + break;
625 + case 'every_poem':
626 + break;
627 + case 'weather':
628 + $content = '多云';
629 + $text_color = $component->text_color ?? 'white';
630 + $text_bg_color = $component->text_bg_color ?? '0xd0cdcc';
631 + $opacity = $component->opacity ? $component->opacity / 100 : '0.5';
632 +
633 + $drawtext .= 'drawtext="'.
634 + 'fontfile=' . escapeshellarg($font) . ':' .
635 + 'text=' . escapeshellarg($content) . ':' .
636 + 'fontsize=' . $this->calcFontSize($component->font_size,$content) . ':' .
637 + 'fontcolor=' . $text_color . '@1.0:' .
638 + 'x=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][0]) . ':' .
639 + 'y=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][1]) . ':' .
640 + 'box=1:boxcolor=' . $text_bg_color . '@' . $opacity . '", ';
641 +
642 + break;
643 + case 'date':
644 + $content = Carbon::now()->format('Y年m月d日H时');
645 + $text_color = $component->text_color ?? 'white';
646 + $text_bg_color = $component->text_bg_color ?? '0xd0cdcc';
647 + $opacity = $component->opacity ? $component->opacity / 100 : '0.5';
648 +
649 + $drawtext .= 'drawtext="'.
650 + 'fontfile=' . escapeshellarg($font) . ':' .
651 + 'text=' . escapeshellarg($content) . ':' .
652 + 'fontsize=' . $this->calcFontSize($component->font_size,$content) . ':' .
653 + 'fontcolor=' . $text_color . '@1.0:' .
654 + 'x=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][0]) . ':' .
655 + 'y=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][1]) . ':' .
656 + 'box=1:boxcolor=' . $text_bg_color . '@' . $opacity . '", ';
657 + break;
658 + case 'feel':
659 + $content = $this->adminMakeVideo->feel;
660 + $text_color = $component->text_color ?? 'white';
661 + $text_bg_color = $component->text_bg_color ?? '0xd0cdcc';
662 + $opacity = $component->opacity ? $component->opacity / 100 : '0.5';
663 +
664 + $drawtext .= 'drawtext="'.
665 + 'fontfile=' . escapeshellarg($font) . ':' .
666 + 'text=' . escapeshellarg($content) . ':' .
667 + 'fontsize=' . $this->calcFontSize($component->font_size,$content) . ':' .
668 + 'fontcolor=' . $text_color . '@1.0:' .
669 + 'x=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][0]) . ':' .
670 + 'y=' . escapeshellarg(VideoTemp::POSITION_FFMPEG[$component->position][1]) . ':' .
671 + 'box=1:boxcolor=' . $text_bg_color . '@' . $opacity . '", ';
672 + break;
673 + }
674 + }
675 +
676 + return rtrim($drawtext,', ');
677 + }
678 +
679 + /**
680 + * @param $width
681 + * @param $content
682 + * @return float
683 + */
684 + public function calcFontSize($width, $content)
685 + {
686 + $max_len = 1;
687 + foreach (explode("\n",$content) as $item){
688 + if (mb_strlen($item) > $max_len){
689 + $max_len = mb_strlen($item);
690 + }
691 + }
692 +
693 + return ceil($this->width * $width / 10 / $max_len);
694 + }
603 } 695 }
......
...@@ -17,9 +17,9 @@ class VideoTemp extends Model ...@@ -17,9 +17,9 @@ class VideoTemp extends Model
17 ]; 17 ];
18 18
19 const POSITION_FFMPEG = [ 19 const POSITION_FFMPEG = [
20 - 'topLeft' => [0, 0], 'topMiddle' => ['(w-text_w)/2', 0], 'topRight' => ['w-text_w', 0], 20 + 'topLeft' => ['0', 'text_h'], 'topMiddle' => ['(w-text_w)/2', 'text_h'], 'topRight' => ['w-text_w', 'text_h'],
21 - 'midLeft' => [0, '(h-text_h)/2'], 'midMiddle' => ['(w-text_w)/2', '(h-text_h)/2'], 'midRight' => ['w-text_w', '(h-text_h)/2'], 21 + 'midLeft' => ['0', '(h-text_h)/2'], 'midMiddle' => ['(w-text_w)/2', '(h-text_h)/2'], 'midRight' => ['w-text_w', '(h-text_h)/2'],
22 - 'botLeft' => [0, 'h-text_h'], 'botMiddle' => ['(w-text_w)/2', 'h-text_h'], 'botRight' => ['w-text_w', 'h-text_h'], 22 + 'botLeft' => ['0', 'h-text_h*2'], 'botMiddle' => ['(w-text_w)/2', 'h-text_h*2'], 'botRight' => ['w-text_w', 'h-text_h*2'],
23 ]; 23 ];
24 24
25 protected $table = 'video_temp'; 25 protected $table = 'video_temp';
......