|
| 1 | +@echo off |
| 2 | + |
| 3 | +rem Usage : |
| 4 | +rem .\thumbnail_maker.bat sample\video.mp4 4 5 |
| 5 | + |
| 6 | +rem set PATH=C:\Users\marlkiller\Downloads\ffmpeg\bin;%PATH% |
| 7 | + |
| 8 | +set param_count=0 |
| 9 | +for %%i in (%*) do ( |
| 10 | +set /a param_count+=1 |
| 11 | +) |
| 12 | + |
| 13 | + |
| 14 | +if %param_count% lss 3 ( |
| 15 | +echo Error: Need at least 3 parameters |
| 16 | +echo Usage: %~f0 sample\video.mp4 4 5 |
| 17 | +exit /b 1 |
| 18 | +) |
| 19 | + |
| 20 | + |
| 21 | +where ffmpeg >nul 2>nul |
| 22 | +if %errorlevel% neq 0 ( |
| 23 | +echo "Please install ffmpeg first" |
| 24 | +exit /b 1 |
| 25 | +) |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | +set time_begin=%time% |
| 30 | +set /A time_begin_minute=%time_begin:~3,2% |
| 31 | +set /A time_begin_second=%time_begin:~-5,2% |
| 32 | +set /A time_begin_mill=%time_begin:~-2,2% |
| 33 | + |
| 34 | + |
| 35 | +echo "Processing %1 %2 %3" |
| 36 | + |
| 37 | +rem tile config |
| 38 | +set "x=%2" |
| 39 | +set "y=%3" |
| 40 | +set /a total_count=%x% * %y% |
| 41 | + |
| 42 | + |
| 43 | +rem echo all arguments: %* |
| 44 | + |
| 45 | +set "abs_video_file=%1" |
| 46 | + |
| 47 | +for %%i in ("%abs_video_file%") do set "video_name=%%~nxi" |
| 48 | + |
| 49 | + |
| 50 | + |
| 51 | +rem ffmpeg config |
| 52 | +set composite_img_width=2048 |
| 53 | +set img_limit=-frames:v 1 -update 1 |
| 54 | +rem set ffmpeg_out= |
| 55 | +set ffmpeg_out=^>^> ffmpeg.out.log 2^>^&1 |
| 56 | + |
| 57 | +echo ffmpeg_outffmpeg_outffmpeg_outffmpeg_out %ffmpeg_out% |
| 58 | + |
| 59 | +rem If the watermark text is garbled, set the font file path here and end with ":" |
| 60 | +rem eg font_file="fontfile=/System/Library/Fonts/Supplemental/Arial Unicode.ttf:" |
| 61 | +set font_file= |
| 62 | +set img_suffix=.jpg |
| 63 | + |
| 64 | + |
| 65 | +rem If scale is placed before tile, the parameters control the resolution of the small tiles; |
| 66 | +rem if scale is placed after tile, the parameters control the resolution of the final composite image.And the padding/margin property in the tile may not be calculated correctly. |
| 67 | +set margin=40 |
| 68 | +set padding=20 |
| 69 | + |
| 70 | +rem SET /A "tile_img_width=(%composite_img_width% - (%padding% * (%x%-1)) - (%margin% * 2)) / %x%" |
| 71 | +rem set "scale=scale=%tile_img_width%:-1," |
| 72 | +rem set "tile=%scale% tile=%x%x%y%:padding=%padding%:margin=%margin%:color=gray," |
| 73 | + |
| 74 | +set "scale=scale=%composite_img_width%:-1," |
| 75 | +set "tile=tile=%x%x%y%:padding=%padding%:margin=%margin%:color=gray,%scale%" |
| 76 | + |
| 77 | + |
| 78 | + |
| 79 | +rem time watermark config |
| 80 | +set "draw_time=drawtext=%font_file%text='%%{pts \: hms}':fontsize=h/15:fontcolor=white:x=w/20:y=h/20," |
| 81 | + |
| 82 | +rem Head info config |
| 83 | +set info_height=150 |
| 84 | + |
| 85 | +echo %abs_video_file% ^>^>^> [%x% X %y% = %total_count%] |
| 86 | + |
| 87 | + |
| 88 | + |
| 89 | + |
| 90 | +rem func generate_tile_by_time |
| 91 | + |
| 92 | +set "out_tile_img_name=%abs_video_file%_time_2%img_suffix%" |
| 93 | +for /f "usebackq delims=" %%a in (`ffprobe -v error -show_entries format^=duration -of default^=noprint_wrappers^=1:nokey^=1 %abs_video_file%`) do set "total_time=%%a" |
| 94 | + |
| 95 | + |
| 96 | +rem Keep two decimal places |
| 97 | +set /a total_time_2=total_time*1000 |
| 98 | +set /a total_count_2=total_count+1 |
| 99 | +set /a chunk=total_time_2/total_count_2+5 |
| 100 | +set chunk=%chunk:~,-3%.%chunk:~-3,2% |
| 101 | + |
| 102 | +rem if %chunk% leq 0 set "chunk=0.01" |
| 103 | + |
| 104 | +echo total_time: %total_time%, chunk: %chunk% |
| 105 | +set "ffmpeg_cmd=ffmpeg -y -i %abs_video_file% %img_limit% -vf "select=(gte(t\,%chunk%))*(isnan(prev_selected_t)+gte(t-prev_selected_t\,%chunk%)),%draw_time% %tile%" -fps_mode auto %out_tile_img_name%" |
| 106 | +echo %ffmpeg_cmd% |
| 107 | +rem call %ffmpeg_cmd% |
| 108 | +cmd /c %ffmpeg_cmd% %ffmpeg_out% |
| 109 | + |
| 110 | + |
| 111 | +rem func generate_video_info |
| 112 | +@setlocal enabledelayedexpansion |
| 113 | + |
| 114 | +set wrap=^ |
| 115 | + |
| 116 | + |
| 117 | +set info= |
| 118 | +for /f "delims=" %%i in ('ffprobe -v quiet -print_format json -show_format -show_streams %abs_video_file%') do ( |
| 119 | +set info=!info!%%i!wrap! |
| 120 | +) |
| 121 | + |
| 122 | +echo !info! > info_json.txt |
| 123 | + |
| 124 | +for /f tokens^=4^ delims^=^" %%i in ('type info_json.txt ^| findstr \"filename\"') do set "filename=%%~i" |
| 125 | +for /f tokens^=4^ delims^=^" %%i in ('type info_json.txt ^| findstr \"size\"') do set "size=%%~i" |
| 126 | + |
| 127 | +rem Filter the third line of matching parameters |
| 128 | +set num=0 |
| 129 | +for /f tokens^=4^ delims^=^" %%i in ('type info_json.txt ^| findstr \"duration\"') do ( |
| 130 | +set /a num+=1 |
| 131 | +if !num!==3 (set duration=%%i) |
| 132 | +) |
| 133 | + |
| 134 | +for /f "tokens=2 delims=:, " %%i in ('type info_json.txt ^| findstr \"width\"') do set "width=%%~i" |
| 135 | +for /f "tokens=2 delims=:, " %%i in ('type info_json.txt ^| findstr \"height\"') do set "height=%%~i" |
| 136 | + |
| 137 | +echo video_info: %filename%,%size%,%duration%,%width%,%height% |
| 138 | + |
| 139 | +set "out_info_txt_name=%abs_video_file%_info%img_suffix%.txt" |
| 140 | +echo,Filename: %filename%> "%out_info_txt_name%" |
| 141 | +echo,Size: %size%>> "%out_info_txt_name%" |
| 142 | +echo,Resolution: %width%x%height%>> "%out_info_txt_name%" |
| 143 | +set /p="duration: %duration%" <nul >> "%out_info_txt_name%" |
| 144 | + |
| 145 | + |
| 146 | +set nl=^& echo. |
| 147 | + |
| 148 | +set "out_info_img_name=%abs_video_file%_info%img_suffix%" |
| 149 | + |
| 150 | +rem converts the \ in the string to / |
| 151 | +set "out_info_txt_name=%out_info_txt_name:\=/%" |
| 152 | +rem converts the : in the string to \: |
| 153 | +set "out_info_txt_name=%out_info_txt_name::=\:%" |
| 154 | +set "ffmpeg_cmd=ffmpeg -y -f lavfi -i color=gray:s=%composite_img_width%x%info_height%:d=1 -update 1 -filter:v "drawtext=%font_file%textfile='%out_info_txt_name%':fontsize=24:fontcolor=white:x=%margin%:y=trunc((h-text_h+%margin%)/2)" %out_info_img_name%" |
| 155 | +echo %ffmpeg_cmd% |
| 156 | +call %ffmpeg_cmd% %ffmpeg_out% |
| 157 | + |
| 158 | +rem func tile_merge_info |
| 159 | + |
| 160 | +set "file_merge=%abs_video_file%_merge%img_suffix%" |
| 161 | +set "ffmpeg_cmd=ffmpeg -y -i %out_tile_img_name% -i %out_info_img_name% -update 1 -frames:v 1 -filter_complex "[0:v]pad=iw:ih+%info_height%+1:0:%info_height%:color=white[top]; [top][1:v]overlay=0:0" %file_merge%" |
| 162 | +echo %ffmpeg_cmd% |
| 163 | +call %ffmpeg_cmd% %ffmpeg_out% |
| 164 | + |
| 165 | + |
| 166 | + |
| 167 | +set time_end=%time% |
| 168 | +set /A time_end_minute=%time_end:~3,2% |
| 169 | +set /A time_end_second=%time_end:~-5,2% |
| 170 | +set /A time_end_mill=%time_end:~-2,2% |
| 171 | + |
| 172 | +if %time_end_mill% lss %time_begin_mill% set /A time_end_mill+=100&set /A time_end_second-=1 |
| 173 | +if %time_end_second% lss %time_begin_second% set /A time_end_second+=60&set /A time_end_minute-=1 |
| 174 | + |
| 175 | +set /A minute=time_end_minute-time_begin_minute |
| 176 | +set /A second=time_end_second-time_begin_second |
| 177 | +set /A mill=time_end_mill-time_begin_mill |
| 178 | + |
| 179 | +echo %time_begin% - %time_end% |
| 180 | +echo "[%video_name%] Command take %minute%:%second%:%mill% to execute." |
| 181 | + |
| 182 | + |
0 commit comments