-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathxffmpeg
More file actions
executable file
·475 lines (464 loc) · 15.8 KB
/
Copy pathxffmpeg
File metadata and controls
executable file
·475 lines (464 loc) · 15.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
#!/bin/bash
#############################################
# author:fang
# version : v1.0
# name : xffmpeg
# dispcripe: use of ffmpeg
# CopyRight@fangyunjiang[42550564@qq.com]
#############################################
source ~/command/common
_oper=0
function show_full_help() {
echo "查看设备"
echo "ffmpeg -list_devices true -f dshow -i dummy"
echo
echo "转发为位图"
echo "ffmpeg -i 1.png -pix_fmt rgb24 1.bmp"
echo
echo "缩放视频"
echo "ffmpeg -i 1.mp4 -s 320x240 -y -acodec copy 2.mp4"
echo "ffmpeg -i 1.mp4 -vf scale=320:240 -y -acodec copy 2.mp4"
echo "ffmpeg -i 1.mp4 -vf scale=iw/2:ih/2 -y -acodec copy 2.mp4"
echo "ffmpeg -i 1.mp4 -vf scale=320:-2 -y -acodec copy 2.mp4"
echo
echo "按照帧剪切视频图片"
echo "ffmpeg -i 1.mp4 -vf \"select=between(n\,0\,10)\" -y -acodec copy 2.mp4"
echo
echo "按照帧生成图片"
echo "ffmpeg -i 1.mp4 -vf \"select=between(n\,0\,2)\" -f image2 fang/%02d.jpg"
echo
echo "提取关键帧 eq(pict_type\,B) eq(pict_type\,P)"
echo "ffmpeg -i 2.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -f image2 fang/%02d.jpeg"
echo
echo "把视频5-10s和15-20s静音"
echo "ffmpeg -i 1.mp4 -af \"volume=enable='between(t,5,10)':volume=0, volume=enable='between(t,15,20)':volume=0\" 2.mp4"
echo
echo "添加水印"
echo "ffmpeg -i 2.mp4 -i logo.png -filter_complex \"overlay=W-w-5:H-h-5\" -codec:a copy -y 3.mp4"
echo "ffmpeg -i 2.mp4 -i logo.png -filter_complex \"overlay=main_w-overlay_w-5:main_h-overlay_h-5\" -codec:a copy -y 3.mp4"
echo
echo "去除水印"
echo "ffmpeg -i 3.mp4 -vf delogo=x=5:y=5:w=72:h=72 4.mp4"
echo
echo "视频或图像加上黑边pad, 原视频1920×1080,新视频2000x1160 40x2=2000-1920 40x2=1160-1080"
echo "ffmpeg -i 2.mp4 -vf pad=2000:1160:40:40:black -y 3.mp4"
echo
echo "添加水印,带scale"
echo "ffmpeg -i 1.mp4 -vf \"movie=test.PNG,scale=100:150[watermask];[in][watermask] overlay=100:100[out]\" -y 2.mp4"
echo
echo "切割成m3u8"
echo "ffmpeg -i 1.mp4 -c:v libx264 -c:a aac -map 0 -f segment -segment_list dist/index.m3u8 -segment_time 5 dist/%03d.ts"
echo "ffmpeg -i 1.mp4 -codec copy -vbsf h264_mp4toannexb -map 0 -f segment -segment_list m3u8/index.m3u8 -segment_time 10 m3u8/out%03d.ts"
}
function cut_video()
{
if [ $# != "4" -a $# != "3" ];then
echo "参数错误,正确格式为:xffmpeg -cut srcVideo [startTime] endTime distVideo"
exit
fi
if [ $# = "3" ];then
if [ "$1" = "$3" ];then
echo "不能覆盖源文件"
exit
fi
echo ffmpeg -ss 0 -to $2 -i "$1" -vcodec copy -acodec copy ${3} -y
ffmpeg -ss 0 -to $2 -i "$1" -vcodec copy -acodec copy ${3} -y
else
if [ "$1" = "$4" ];then
echo "不能覆盖源文件"
exit
fi
echo ffmpeg -ss $2 -to $3 -i "$1" -vcodec libx264 -crf 30 -acodec copy ${4} -y
ffmpeg -ss $2 -to $3 -i "$1" -vcodec libx264 -crf 30 -acodec copy ${4} -y
fi
}
function join_video()
{
local i n arr
if [ $# -lt 3 ];then
echo "参数错误,正确格式为:xffmpeg -join srcVideo1 srcVideo2 ..."
exit
fi
n="$#"
arr=("$@")
echo "file ${arr[0]}" > .__video_list
for ((i=1; i<n-1; i++));do
echo "file ${arr[i]}" >> .__video_list
done
echo ffmpeg -f concat -i .__video_list -c copy ${arr[i]} -y
ffmpeg -f concat -i .__video_list -c copy ${arr[i]} -y
rm .__video_list
}
function join_video_ex()
{
local i s n arr extname
if [ $# != 3 ];then
echo "参数错误,正确格式为:xffmpeg -joinEx 1 n distVideo"
exit
fi
extname=`__get_extname "$3"`
s=$1
n=$2
echo "file $s.${extname}" > .__video_list
for ((i=s+1; i<=n; i++));do
echo "file $i.${extname}" >> .__video_list
done
echo ffmpeg -f concat -i .__video_list -c copy "$3" -y
ffmpeg -f concat -i .__video_list -c copy "$3" -y
rm .__video_list
}
function concat_image()
{
local i n arr stack line ow ows max o list
stack="vstack"
if [ "$1" = "v" ];then
stack="vstack"
shift
elif [ "$1" = "h" ];then
stack="hstack"
shift
fi
if [ $# -lt 3 ];then
echo "参数错误,正确格式为:xffmpeg -concat srcImage1 srcImage2 ..."
exit
fi
n="$#"
arr=("$@")
line=""
if [ "$stack" = "vstack" ];then
for ((i=0; i<n-1; i++));do
ow=`ffmpeg -i "${arr[i]}" 2>&1 | grep Video: | grep -Po '\d+x\d+'`
ow=${ow%%x*}
ows="$ows $ow"
done
ows=($ows)
max=${ows[0]}
for o in ${ows[@]};do
if (( o > max ));then
max=$o
fi
done
for ((i=0; i<n-1; i++));do
if [ "$max" != "${ows[i]}" ];then
scale_video "${arr[i]}" "$max" "xxx${arr[i]}"
line="${line} -i xxx${arr[i]}"
list="$list xxx${arr[i]}"
else
line="${line} -i ${arr[i]}"
fi
done
echo ffmpeg ${line} -filter_complex ${stack} ${arr[i]} -y
ffmpeg ${line} -filter_complex ${stack} ${arr[i]} -y
rm -f ${list}
else
for ((i=0; i<n-1; i++));do
ow=`ffmpeg -i "${arr[i]}" 2>&1 | grep Video: | grep -Po '\d+x\d+'`
ow=${ow##*x}
ows="$ows $ow"
done
ows=($ows)
max=${ows[0]}
for o in ${ows[@]};do
if (( o > max ));then
max=$o
fi
done
for ((i=0; i<n-1; i++));do
if [ "$max" != "${ows[i]}" ];then
scale_video "${arr[i]}" 0 "$max" "xxx${arr[i]}"
line="${line} -i xxx${arr[i]}"
list="$list xxx${arr[i]}"
else
line="${line} -i ${arr[i]}"
fi
done
echo ffmpeg ${line} -filter_complex ${stack} ${arr[i]} -y
ffmpeg ${line} -filter_complex ${stack} ${arr[i]} -y
rm -f ${list}
fi
}
function logo_video()
{
local dist overlay
if [ $# != "5" -a $# != "7" ];then
echo "参数错误,正确格式为:xffmpeg -logo video logo logoX logoY [logoWidth logoHeight] distVideo"
exit
fi
if [ $# = "7" ];then
echo ffmpeg -i $2 -s $5x$6 .__$2
ffmpeg -i $2 -s $5x$6 .__$2
dist="$7"
else
cp $2 .__$2
dist="$5"
fi
if (($3<0));then
if (($4<0));then
overlay="W-w+$3:H-h+$4"
else
overlay="W-w+$3:$4"
fi
else
if (($4<0));then
overlay="$3:H-h+$4"
else
overlay="$3:$4"
fi
fi
echo ffmpeg -i "$1" -vf "movie=.__$2[watermark];[in][watermark] overlay=$overlay[out]" "$dist" -y
ffmpeg -i "$1" -vf "movie=.__$2[watermark];[in][watermark] overlay=$overlay[out]" "$dist" -y
rm .__$2
}
function cover_video()
{
local wh
if [ $# != "3" ];then
echo "参数错误,正确格式为:xffmpeg -cover srcVideo srcImage distVideo"
exit
fi
get_video_width_height $1 wh
echo ffmpeg -i "$1" -i "$2" -filter_complex [1:v]scale=${wh}[ovrl],[0:v][ovrl]overlay=enable='between(n\,0\,1)' -y "$3"
ffmpeg -i "$1" -i "$2" -filter_complex [1:v]scale=${wh}[ovrl],[0:v][ovrl]overlay=enable='between(n\,0\,1)' -y "$3"
# 不计算宽度
#ffmpeg -i 1.mp4 -i 1.png -filter_complex overlay=enable='between(n\,0\,1)' -y 2.mp4
# 只添加封面
#ffmpeg -i 1.mp4 -i 1.png -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic -y 2.mp4
}
function set_contrast_brightness_video()
{
if [ $# != "4" ];then
echo "参数错误,正确格式为:xffmpeg -bright srcVideo contrast brightness distVideo"
exit
fi
echo ffmpeg -i $1 -vf eq=contrast=$2:brightness=$3 -y $4
ffmpeg -i $1 -vf eq=contrast=$2:brightness=$3 -y $4
}
function get_video_time()
{
local list sum var
list=($(ffmpeg -i "$1" 2>&1|grep Duration| cut -d ' ' -f 4 | sed 's/\..*//'|sed 's/:/ /g'))
if [ -z "$list" ];then
echo "这不是一个视频文件"
exit
fi
sum=0
for var in "${list[@]}";do
((sum=sum*60+var))
done
eval $2=$sum
}
function get_video_width_height()
{
local ret
ret=$(ffmpeg -i "$1" 2>&1|grep Stream.*Video|cut -d ',' -f 3|sed 's/x/:/'|sed 's/\s//g')
eval $2="$ret"
}
function set_audio_video()
{
local vtime atime n joinstr
if [ $# != "3" ];then
echo "参数错误,正确格式为:xffmpeg -audio srcVideo srcAudio distVideo"
exit
fi
get_video_time "$1" vtime
get_video_time "$2" atime
((n=(vtime-1)/atime+1))
if ((n>1));then
joinstr=""
for ((i=0;i<n;i++));do
joinstr="$joinstr $2"
done
join_video $joinstr __audio.mp3
else
cp "$2" __audio.mp3
fi
echo ffmpeg -i $1 -c:v copy -an __video.mp4
ffmpeg -i $1 -c:v copy -an __video.mp4
echo ffmpeg -i __video.mp4 -i __audio.mp3 -t $vtime -c copy -y $3
ffmpeg -i __video.mp4 -i __audio.mp3 -t $vtime -c copy -y $3
#ffmpeg -i __video.mp4 -i __audio.mp3 -t $vtime –vcodec copy –acodec copy -y $3
rm __audio.mp3
rm __video.mp4
}
function split_video_audio()
{
if [ $# != "3" ];then
echo "参数错误,正确格式为:xffmpeg -split srcVideo video|audio distFile"
exit
fi
if [ "$2" = "video" ];then
ffmpeg -i "$1" -vcodec copy -an "$3"
elif [ "$2" = "audio" ];then
# ffmpeg -i "$1" -acodec copy -vn "$3"
ffmpeg -i "$1" -b:a 128k "$3"
else
echo "参数错误,正确格式为:xffmpeg -split srcVideo video|audio distFile"
fi
}
function crop_video()
{
if [ $# = "4" ];then
if [ "${2/iw/}" != "$2" -o "${3/ih/}" != "$3" ]; then
echo ffmpeg -i "$1" -vf crop=${2}:${3}:0:0 -y "$4"
ffmpeg -i "$1" -vf crop=${2}:${3}:0:0 -y "$4"
else
echo ffmpeg -i "$1" -vf crop=iw-${2}:ih-${3}:${2}:${3} -y "$4"
ffmpeg -i "$1" -vf crop=iw-${2}:ih-${3}:${2}:${3} -y "$4"
fi
exit
fi
if [ $# != "6" ];then
echo "参数错误,正确格式为:xffmpeg -crop srcVideo x y width height distVideo"
exit
fi
echo ffmpeg -i "$1" -vf crop=${4}:${5}:${2}:${3} -y "$6"
ffmpeg -i "$1" -vf crop=${4}:${5}:${2}:${3} -y "$6"
}
function scale_video()
{
local scale ow
if [ $# = "4" ];then
if [ "$2" != "0" ];then
echo ffmpeg -i "$1" -s ${2}x${3} -y -acodec copy "$4"
ffmpeg -i "$1" -s ${2}x${3} -y -acodec copy "$4"
else
ow=`ffmpeg -i "$1" 2>&1 | grep Video: | grep -Po '\d+x\d+'`
ow=${ow##*x}
scale=`awk 'BEGIN{printf("%.2f", "'$ow'" / "'$3'")}'`
echo ffmpeg -i "$1" -vf scale=iw/${scale}:$3 -y -acodec copy "$4"
ffmpeg -i "$1" -vf scale=iw/${scale}:$3 -y -acodec copy "$4"
fi
elif [ $# = "3" ];then
ow=`ffmpeg -i "$1" 2>&1 | grep Video: | grep -Po '\d+x\d+'`
ow=${ow%%x*}
scale=`awk 'BEGIN{printf("%.2f", "'$ow'" / "'$2'")}'`
echo ffmpeg -i "$1" -vf scale=$2:ih/${scale} -y -acodec copy "$3"
ffmpeg -i "$1" -vf scale=$2:ih/${scale} -y -acodec copy "$3"
else
echo "参数错误,正确格式为:xffmpeg -scale srcVideo width [height] distVideo"
fi
}
function scale_video_ex() {
if [ $# = "3" -o $# = "2" ];then
if ! [ -f "__$1" ];then
cp "$1" "__$1"
fi
scale_video "__$1" $2 $3 $1
else
echo "参数错误,正确格式为:xffmpeg -scale srcVideo width [height]"
fi
}
function reverse_video()
{
if [ $# != "2" ];then
echo "参数错误,正确格式为:xffmpeg -reverse srcVideo distVideo"
exit
fi
ffmpeg -i "$1" -vf reverse -y "$2"
}
function fast_video()
{
local rate
if [ $# != "3" ];then
echo "参数错误,正确格式为:xffmpeg -fast rate srcVideo distVideo"
exit
fi
rate=$(echo "scale=6;1/${1}"|bc)
ffmpeg -i "$2" -filter_complex "[0:v]setpts=${1}*PTS[v];[0:a]atempo=${rate}[a]" -map "[v]" -map "[a]" -y "$3"
}
function get_video_image()
{
if [ $# != "3" ];then
echo "参数错误,正确格式为:xffmpeg -image srcVideo time distImage"
exit
fi
ffmpeg -ss $2 -i "$1" -vframes 1 -q:v 2 "$3"
}
function capture_desktop_video()
{
local microphone
if [ $# != "1" -a $# != "2" ];then
echo "参数错误,正确格式为:xffmpeg -c 1.mp4|1.mp3 [1:hasMicrophone]"
exit
fi
# 必须安装 https://github.com/rdp/screen-capture-recorder-to-video-windows-free
microphone="麦克风阵列 (适用于数字麦克风的英特尔® 智音技术)" # 搜索设备管理器 -> 音频输入和输出 -> 双击micphone -> 详情信息 -> 复制值(V)
if [ "$1" = *.mp3 ];then
if [ -z "$2" ];then
ffmpeg -y -f dshow -i audio="virtual-audio-capturer" "$1"
else
ffmpeg -y -f dshow -i audio="${microphone}" -f dshow -i audio="virtual-audio-capturer" -filter_complex amix=inputs=2:duration=first:dropout_transition=0 "$1"
fi
else
if [ -z "$2" ];then
ffmpeg -y -f dshow -i audio="virtual-audio-capturer":video="screen-capture-recorder" "$1"
else
ffmpeg -y -f dshow -i audio="${microphone}" -f dshow -i audio="virtual-audio-capturer" -filter_complex amix=inputs=2:duration=first:dropout_transition=0 -f dshow -i video="screen-capture-recorder" -pix_fmt yuv420p "$1"
fi
fi
}
function get_video_info()
{
n="$#"
for ((i=0; i<n; i++));do
if [ "${1%%.png}" != "$1" -o "${1%%.jpg}" != "$1" ];then
ffmpeg -i "$1" 2>&1 | grep Video: | grep -Po '\d+x\d+'
else
# ffprobe -select_streams v:0 -v quiet -show_streams -of json -i "$1"
# echo ffprobe -v quiet -select_streams v:0 -show_entries stream=nb_frames,width,height,duration -of default=nokey=0:noprint_wrappers=1 "$1"
ffprobe -v quiet -select_streams v:0 -show_entries stream=nb_frames,width,height,duration -of default=nokey=0:noprint_wrappers=1 "$1"
fi
shift
done
}
function show_help()
{
local -a list
list="help"
list=("${list[@]}" "Usage: xffmpeg [OPTIONS]")
list=("${list[@]}" " -logo video logo logoX logoY [logoWidth logoHeight] distVideo: [设置logo -10 -10表示右下角] xffmpeg -logo 1.mp4 1.jpg 10 10 [100 100] 2.mp4")
list=("${list[@]}" " -cut srcVideo [startTime] endTime distVideo: [剪切] xffmpeg -cut 1.mp4 05.000 10.0000 2.mp4 ,如果只设置了一个时间,则为endTime")
list=("${list[@]}" " -join srcVideo1 srcVideo2 ... distVideo: [连接] xffmpeg -join 1.mp4 2.mp4 3.mp4")
list=("${list[@]}" " -joinEx 1 n distVideo: [连接] xffmpeg -joinEx 1 10 2.mp4")
list=("${list[@]}" " -cover srcVideo srcImage distVideo: [封面] xffmpeg -cover 1.mp4 1.png 2.mp4")
list=("${list[@]}" " -bright srcVideo contrast brightness distVideo: [对比度亮度] xffmpeg -bright 1.mp4 1.1 -0.1 2.mp4")
list=("${list[@]}" " -audio srcVideo srcAudio distVideo: [添加音频] xffmpeg -audio 1.mp4 1.mp3 2.mp4")
list=("${list[@]}" " -split srcVideo video|audio distFile: [分离音视频] xffmpeg -split 1.mp4 video 2.mp4")
list=("${list[@]}" " -crop srcMedia x y width height distMedia: [裁剪视频|图片,可以使用数字和iw,ih的组合,如果只有x,y且是数据则从x,y剪切到左边和底边,如果只有两位数字且是包含iw和ih,则从0,0剪切到这个位置] xffmpeg -crop 1.mp4|1.jpg iw/4 ih/4 iw/2 ih/2 2.mp4|2.jpg; xffmpeg -crop 1.jpg 50 50 2.jpg; xffmpeg -crop 1.jpg iw-50 iw-50 2.jpg")
list=("${list[@]}" " -scale srcMedia width[0] [height] distMedia: [缩放视频|图片,如果没有height,以width为比列缩放,如果width为0,则以height为比例缩放] xffmpeg -scale 1.mp4|1.jpg width height 2.mp4|2.jpg")
list=("${list[@]}" " -s srcMedia width[0] [height]: [缩放视频|图片,自动备份文件")
list=("${list[@]}" " -reverse srcVideo distVideo: [倒放视频] xffmpeg -reverse 1.mp4 2.mp4")
list=("${list[@]}" " -fast rate srcVideo distVideo: [倒放视频] xffmpeg -fast 0.9 1.mp4 2.m4")
list=("${list[@]}" " -image srcVideo time distImage: [截图] xffmpeg -image 1.mp4 10 1.jpg")
list=("${list[@]}" " -concat [v|h] srcImage1 srcImage2 ... distImage: [横向|纵向连接图片] xffmpeg -concat h 1.jpg 2.jpg 3.jpg")
list=("${list[@]}" " -i srcVideo: [查看视频信息]")
list=("${list[@]}" " -c distFile [hasMicrophone]: [录制桌面视频] xffmpeg -c 1.mp4|1.mp3")
list=("${list[@]}" " -h: show help ")
list=("${list[@]}" " --help: show full help ")
__msgbox "${list[@]}"
exit
}
function main()
{
__init_opts "$@"
__check_opts "-h" && show_help
__check_opts "--help" && show_full_help
__check_opts "-cut" && cut_video ${_args_[@]}
__check_opts "-join" && join_video ${_args_[@]}
__check_opts "-joinEx" && join_video_ex ${_args_[@]}
__check_opts "-logo" && logo_video ${_args_[@]}
__check_opts "-cover" && cover_video ${_args_[@]}
__check_opts "-bright" && set_contrast_brightness_video ${_args_[@]}
__check_opts "-audio" && set_audio_video ${_args_[@]}
__check_opts "-split" && split_video_audio ${_args_[@]}
__check_opts "-crop" && crop_video ${_args_[@]}
__check_opts "-scale" && scale_video ${_args_[@]}
__check_opts "-s" && scale_video_ex ${_args_[@]}
__check_opts "-reverse" && reverse_video ${_args_[@]}
__check_opts "-fast" && fast_video ${_args_[@]}
__check_opts "-image" && get_video_image ${_args_[@]}
__check_opts "-concat" && concat_image ${_args_[@]}
__check_opts "-c" && capture_desktop_video ${_args_[@]}
__check_opts "-i" && get_video_info ${_args_[@]}
}
main "$@"