-
Notifications
You must be signed in to change notification settings - Fork 0
/
vydGenerateVideo
executable file
·157 lines (137 loc) · 7.75 KB
/
vydGenerateVideo
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
#!/bin/bash
# Define some colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Initialize total elapsed time
TOTAL_START_TIME=$(date +%s)
function usage {
echo -e "${YELLOW}Usage: $0 -i INPUTFILE -f FORMAT [-c CODEC] [-s STARTTIME] [-e ENDTIME] [-w WIDTH|-h HEIGHT] [-k KEYFRAME_DISTANCE] [-a AUTO_ALT_REF] [-l LAG_IN_FRAMES] BITRATE_PAIRS...${NC}"
echo ""
echo "Options:"
echo -e " ${GREEN}-i INPUTFILE${NC} Input file"
echo -e " ${GREEN}-f FORMAT${NC} Output format (either 'mp4' or 'webm')"
echo -e " ${GREEN}-c CODEC${NC} Codec (either 'h264' or 'h265'). Only available when format is 'mp4'. Defaults to 'h264'"
echo -e " ${GREEN}-s STARTTIME${NC} Start time (format: hh:mm:ss.mmm)"
echo -e " ${GREEN}-e ENDTIME${NC} End time (format: hh:mm:ss.mmm)"
echo -e " ${GREEN}-w WIDTH${NC} Width to scale the video to, keeping aspect ratio"
echo -e " ${GREEN}-h HEIGHT${NC} Height to scale the video to, keeping aspect ratio"
echo -e " ${GREEN}-k KEYFRAME_DISTANCE${NC} Keyframe distance (defaults to 'auto' for mp4 and '128' for webm). The value specifies the maximum distance between key frames. In MP4, if not provided, keyframe distance is automatically determined by FFmpeg. In WEBM, if not provided, keyframe distance defaults to 128 frames. Minimum value is 0 (every frame is a keyframe), and there's no specified maximum value, although a very large value could lead to poor performance."
echo -e " ${GREEN}-a AUTO_ALT_REF${NC} Enable use of alternative reference frames (only for 'webm'). Default value is 0, and it can be 0 or 1."
echo -e " ${GREEN}-l LAG_IN_FRAMES${NC} Maximum number of frames to look ahead for frame type decision (only for 'webm'). Default value is 16, and it can be between 0 to 25."
echo -e " ${GREEN}-r FRAME_DROP_RATIO${NC} Frame drop ratio (defaults to 1, indicating no frames dropped). It must be 1 or a multiple of 2. A value of 2 will drop half the frames, and so on."
echo ""
echo "Arguments:"
echo -e " ${RED}BITRATE_PAIRS${NC} Bitrate pairs (format: TARGET_BITRATE:MAX_BITRATE for 'mp4' and TARGET_BITRATE for 'webm')"
echo ""
echo "Examples:"
echo -e "${YELLOW}$0 -i input.mp4 -f mp4 -c h265 -s 00:00:00 -e 00:05:00 -w 640 -k auto 1000K:1500K 1500K:2000K${NC}"
echo -e "${YELLOW}$0 -i input.webm -f webm -s 00:00:00 -e 00:05:00 -h 480 -k 128 -a 1 -l 16 1000K${NC}"
exit
}
START_TIME="00:00:00.000"
START_TIME="00:00:00.000"
END_TIME=""
SCALE=""
KEYFRAME_DISTANCE="auto"
AUTO_ALT_REF="0"
LAG_IN_FRAMES="16"
FRAME_DROP_RATIO="1"
CODEC="h264"
while getopts i:s:e:f:c:w:h:k:a:l:r: flag
do
case "${flag}" in
i) INPUT_FILE=${OPTARG};;
s) START_TIME=${OPTARG};;
e) END_TIME=${OPTARG};;
f) FORMAT=${OPTARG};;
c) CODEC=${OPTARG};;
w) SCALE=${OPTARG}:-2;;
h) SCALE=-2:${OPTARG};;
k) KEYFRAME_DISTANCE=${OPTARG};;
a) AUTO_ALT_REF=${OPTARG};;
l) LAG_IN_FRAMES=${OPTARG};;
r) FRAME_DROP_RATIO=${OPTARG};;
?) echo "Invalid option: -${OPTARG}" >&2; exit 1;;
esac
done
shift $((OPTIND-1))
# Validate FRAME_DROP_RATIO. It must be 1 or a multiple of 2.
if ! [[ "$FRAME_DROP_RATIO" =~ ^[1-9][0-9]*$ ]] || ((FRAME_DROP_RATIO > 1 && FRAME_DROP_RATIO % 2 != 0)); then
echo -e "${RED}Invalid frame drop ratio: ${FRAME_DROP_RATIO}. It must be 1 or a multiple of 2.${NC}"
exit 1
fi
function generate {
if [ "$FORMAT" = "mp4" ]; then
if [ "$CODEC" = "h264" ]; then
CODEC="libx264"
KEYFRAME_PARAM="-x264-params keyint=$KEYFRAME_DISTANCE:scenecut=0"
elif [ "$CODEC" = "h265" ]; then
CODEC="libx265"
KEYFRAME_PARAM="-x265-params keyint=$KEYFRAME_DISTANCE:scenecut=0"
else
echo "Invalid codec: ${CODEC}. Only 'h264' and 'h265' are supported when format is 'mp4'."
exit 1
fi
PIX_FMT="yuv420p"
PROFILE="-profile:v main -level:v 3.1"
MOVFLAGS="-movflags +faststart"
PRESET="-preset veryslow"
if [ "$KEYFRAME_DISTANCE" = "auto" ]; then
KEYFRAME_PARAM=""
fi
ADDITIONAL_PARAMS=""
elif [ "$FORMAT" = "webm" ]; then
CODEC="libvpx-vp9"
PIX_FMT="yuv420p"
PROFILE=""
MOVFLAGS=""
PRESET=""
if [ "$KEYFRAME_DISTANCE" = "auto" ]; then
KEYFRAME_DISTANCE="128"
fi
KEYFRAME_PARAM="-g $KEYFRAME_DISTANCE"
ADDITIONAL_PARAMS="-auto-alt-ref $AUTO_ALT_REF -lag-in-frames $LAG_IN_FRAMES"
else
echo "Invalid format: ${FORMAT}. Only 'mp4' and 'webm' are supported."
exit 1
fi
if ((FRAME_DROP_RATIO > 1)); then
ADDITIONAL_PARAMS+=" -vf 'select=mod(n,$FRAME_DROP_RATIO)',setpts='PTS/FRAME_RATE' -vsync vfr"
fi
for bitrate in "$@"; do
# Start time for this job
JOB_START_TIME=$(date +%s)
if [ "$FORMAT" = "mp4" ]; then
IFS=":" read -r TARGET_BITRATE MAX_BITRATE <<< "$bitrate"
OUTPUT_FILE="${INPUT_FILE%.*}-vbr_${TARGET_BITRATE}-${MAX_BITRATE}-start_${START_TIME//:/-}-end_${END_TIME//:/-}-scale_${SCALE//:/x}-keyframe_${KEYFRAME_DISTANCE}-codec_${CODEC}.${FORMAT}"
echo -e "${GREEN}Processing file '${INPUT_FILE}' with format '${FORMAT}', start time '${START_TIME}', end time '${END_TIME}', scale '${SCALE}', keyframe distance '${KEYFRAME_DISTANCE}', codec '${CODEC}', target bitrate: ${TARGET_BITRATE} and max bitrate: ${MAX_BITRATE}${NC}"
ffmpeg -y -ss "$START_TIME" -i "$INPUT_FILE" ${END_TIME:+-to "$END_TIME"} -vcodec $CODEC -pix_fmt $PIX_FMT $PROFILE -vf "scale=${SCALE}" $PRESET -pass 1 -b:v $TARGET_BITRATE $KEYFRAME_PARAM $ADDITIONAL_PARAMS -an -f $FORMAT /dev/null
ffmpeg -ss "$START_TIME" -i "$INPUT_FILE" ${END_TIME:+-to "$END_TIME"} -vcodec $CODEC -pix_fmt $PIX_FMT $PROFILE -vf "scale=${SCALE}" $PRESET -pass 2 -b:v $MAX_BITRATE $KEYFRAME_PARAM $ADDITIONAL_PARAMS $MOVFLAGS "$OUTPUT_FILE"
else
TARGET_BITRATE="$bitrate"
OUTPUT_FILE="${INPUT_FILE%.*}-vbr_${TARGET_BITRATE}-start_${START_TIME//:/-}-end_${END_TIME//:/-}-scale_${SCALE//:/x}-keyframe_${KEYFRAME_DISTANCE}-altref_${AUTO_ALT_REF}-lag_${LAG_IN_FRAMES}.${FORMAT}"
echo -e "${GREEN}Processing file '${INPUT_FILE}' with format '${FORMAT}', start time '${START_TIME}', end time '${END_TIME}', scale '${SCALE}', keyframe distance '${KEYFRAME_DISTANCE}', auto alt ref '${AUTO_ALT_REF}', lag in frames '${LAG_IN_FRAMES}', target bitrate: ${TARGET_BITRATE}${NC}"
ffmpeg -ss "$START_TIME" -i "$INPUT_FILE" ${END_TIME:+-to "$END_TIME"} -vcodec $CODEC -pix_fmt $PIX_FMT $PROFILE -vf "scale=${SCALE}" $PRESET -b:v $TARGET_BITRATE $KEYFRAME_PARAM $ADDITIONAL_PARAMS $MOVFLAGS "$OUTPUT_FILE"
fi
echo -e "${GREEN}Done processing file '${INPUT_FILE}' with format '${FORMAT}', start time '${START_TIME}', end time '${END_TIME}', scale '${SCALE}', keyframe distance '${KEYFRAME_DISTANCE}', auto alt ref '${AUTO_ALT_REF}', lag in frames '${LAG_IN_FRAMES}', target bitrate: ${TARGET_BITRATE} and max bitrate: ${MAX_BITRATE}${NC}"
# Calculate elapsed time for this job
JOB_END_TIME=$(date +%s)
JOB_ELAPSED_TIME=$((JOB_END_TIME - JOB_START_TIME))
echo -e "${YELLOW}Elapsed time for this job: $JOB_ELAPSED_TIME seconds${NC}"
done
}
if [ -z "$INPUT_FILE" ]; then
echo "Input video is required" >&2
usage
fi
if [ -z "$FORMAT" ]; then
echo "Output format is required" >&2
usage
fi
# Calculate total elapsed time
TOTAL_END_TIME=$(date +%s)
TOTAL_ELAPSED_TIME=$((TOTAL_END_TIME - TOTAL_START_TIME))
echo -e "${YELLOW}Total elapsed time: $TOTAL_ELAPSED_TIME seconds${NC}"
generate "$@"