Skip to content

Instantly share code, notes, and snippets.

@7sDream
Last active August 27, 2023 18:46
Show Gist options
  • Save 7sDream/988314e29cac7570aa127406b436cab4 to your computer and use it in GitHub Desktop.
Save 7sDream/988314e29cac7570aa127406b436cab4 to your computer and use it in GitHub Desktop.
Convert video to meet bilibili's requirement. Video: 1080p60, H264, avg bitrate 6k, max bitrate 24k, max key frame interval 10s; Audio: aac, 44100Hz, 192k. With optional GPU acceleration support.
#!/bin/bash
# ===== setting =====
FORMAT=mp4
VIDEO_CODEC=libx264
VIDEO_GPU_CODEC=h264_videotoolbox
PROFILE=high
LEVEL=4.2
PRESET=veryslow
FPS=60
MAX_KEY_FRAME_INTERVAL_SECONDS=10
AUDIO_BITRATE=192
AUDIO_FREQ=44100
VIDEO_BITRATE_BUFF=200
VIDEO_AVG_BITRATE=6000
VIDEO_MAX_BITRATE=24000
QMAX=30
QMIN=16
REF=4
MAKE_FFMPEG_QUITE="-hide_banner -loglevel warning -stats"
# ===== calculation ======
VIDEO_AVG_BITRATE=$(( $(( $VIDEO_AVG_BITRATE - $VIDEO_BITRATE_BUFF)) / 100 * 100 ))
VIDEO_MAX_BITRATE=$(( $(( $VIDEO_MAX_BITRATE - $VIDEO_BITRATE_BUFF)) / 100 * 100 ))
KEYINT=$(( $(( $FPS - 1)) * $MAX_KEY_FRAME_INTERVAL_SECONDS ))
MIN_KEYINT=$(( $KEYINT / 10 ))
# ===== CLI args =====
if [ "$#" -lt 2 ]; then
echo "Usage: $0 <origin-file> <output-file> [use-gpu]"
exit 1
fi
INPUT=$1
OUTPUT=$2
USE_GPU=$3
if [ "$USE_GPU" = "true" ]; then
VIDEO_CODEC=$VIDEO_GPU_CODEC
fi
# ===== args =====
VIDEO_ARGS="-c:v $VIDEO_CODEC -profile:v $PROFILE -level $LEVEL -b:v ${VIDEO_AVG_BITRATE}k -maxrate ${VIDEO_MAX_BITRATE}k -bufsize ${VIDEO_MAX_BITRATE}k -qmin $QMIN -qmax $QMAX -refs:v $REF -g $KEYINT -keyint_min $MIN_KEYINT -color_range 1"
if [ "$USE_GPU" != "true" ]; then
VIDEO_ARGS="$VIDEO_ARGS -preset:v $PRESET"
fi
AUDIO_PASS1_ARGS="-an"
AUDIO_PASS2_ARGS="-c:a aac -b:a ${AUDIO_BITRATE}k -ar $AUDIO_FREQ -metadata:s:a:0 language=zho"
OUTPUT_ARGS="-write_tmcd 0 -dn -sn -f $FORMAT -y"
INPUT_ARGS="-map 0:v -map 0:a:0"
COMMON_ARGS="$MAKE_FFMPEG_QUITE $INPUT_ARGS $VIDEO_ARGS"
PASS1_ARGS="$COMMON_ARGS -pass 1 -passlogfile $INPUT $AUDIO_PASS1_ARGS $OUTPUT_ARGS"
PASS2_ARGS="$COMMON_ARGS -pass 2 -passlogfile $INPUT $AUDIO_PASS2_ARGS $OUTPUT_ARGS"
GPU_ARGS="$COMMON_ARGS $AUDIO_PASS2_ARGS $OUTPUT_ARGS"
# ===== trap =====
function cleanup {
if [ "$USE_GPU" != "true" ]; then
echo -n "cleaning 2 pass log file..."
find . -type f -regex "$INPUT-*.log.mbtree" -delete
find . -type f -regex "$INPUT-*.log" -delete
echo "done"
fi
exit
}
trap cleanup INT
# ===== RUN =====
echo "$INPUT --> $OUTPUT"
echo
if [ "$USE_GPU" = "true" ]; then
echo "Args(With GPU Acceleration): $GPU_ARGS"
echo
ffmpeg -i "$INPUT" $GPU_ARGS "$OUTPUT"
echo
else
echo "First pass args: $PASS1_ARGS"
echo
ffmpeg -i "$INPUT" $PASS1_ARGS /dev/null
echo
echo "Second pass args: $PASS2_ARGS"
echo
ffmpeg -i "$INPUT" $PASS2_ARGS "$OUTPUT"
echo
fi
cleanup
@7sDream
Copy link
Author

7sDream commented Aug 8, 2019

Usage: ffmpeg_bilibili.sh input.mov output.mp4

Will start a two-pass encoding.

If you are using Mac, use ffmpeg_bilibili.sh input.mov output.mp4 true will use GPU acceleration but only one-pass and reduce ref frames to 2.

In my case (MBP2018,13',i7,Intel Iris Plus Graphics 655), use GPU can be 15X faster then CPU.

@TheOppaiDragon
Copy link

my video is already mp4. What i need to do?

@7sDream
Copy link
Author

7sDream commented Aug 27, 2023

my video is already mp4. What i need to do?

@TheOppaiDragon
The purpose of this script is to re-encode some videos so that they are not recompressed by the platform.
If you don't care about recompress(it's true for most people/case), just upload it directlly is enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment