Skip to content

Instantly share code, notes, and snippets.

@blurgyy
Last active July 14, 2021 12:07
Show Gist options
  • Select an option

  • Save blurgyy/5ac9ec87645684be0a37d95ab4d733cf to your computer and use it in GitHub Desktop.

Select an option

Save blurgyy/5ac9ec87645684be0a37d95ab4d733cf to your computer and use it in GitHub Desktop.
Shell script to convert m3u8 playlist(s) to mp4 video(s) with ffmpeg.
#!/usr/bin/env bash
# Convert m3u8 playlist(s) to mp4 video(s) with ffmpeg.
#
# Usage:
#
# m3u82mp4.sh -i <input_url> [-i <more_input_urls>] [-d <output_dir>]
#
# Example:
#
# $0 -d /tmp/cat-video \
# -i /path/to/playlist.m3u8 \
# -i https://link.to/playlist.m3u8
#
# Upon successful execution, the above example will generate two videos
# in the directory "/tmp/cat-video":
#
# 1. /tmp/cat-video/%path%to%playlist.m3u8.mp4
# 2. /tmp/cat-video/https:%%link.to%playlist.m3u8.mp4
#
# Additional information:
#
# 1. Conversion will occur in the background. Log files, output video
# files, process pids will be saved to a file ".m3u82mp4.summary" in
# the working directory where the script is executed.
# 2. Existing files will not be overwritten.
set -Eeuo pipefail
declare -a input_paths
has_input=0
log_dir=~/.local/share/m3u82mp4
output_dir="$PWD"
summary_file="$PWD"/.m3u82mp4.summary
function playlist-to-mp4() {
input_url=$1
if [[ -e "$input_url" ]]; then
input_url=$(realpath "$input_url")
fi
output_path=${input_url// /%}
output_path=${output_path//\//%}
output_path="$output_path".mp4
output_path="$output_dir/$output_path"
log_path="$input_url"
log_path=${log_path// /%}
log_path=${log_path//\//%}
log_path="$log_dir/$log_path"
ffmpeg >"$log_path" 2>&1 \
-protocol_whitelist tcp,file,https,crypto,tls,httpproxy \
-i "$input_url" \
-bsf:a aac_adtstoasc -vcodec copy -c copy \
"$output_path" -n &
tee -a "$summary_file" <<EOF
Conversion started ..
input: $input_url
log file: $log_path
output video file: $output_path
pid: $(lsof -Fp "$log_path" | sed 's/p//')
EOF
}
function show-help() {
cat <<EOF
Usage:
$0 -i <input_url> [-i <more_input_urls>] [-d <output_dir>]
Example:
$0 -d /tmp/cat-video \\
-i /path/to/playlist.m3u8 \\
-i https://link.to/playlist.m3u8
Upon successful execution, the above example will generate two videos
in the directory "/tmp/cat-video":
1. /tmp/cat-video/%path%to%playlist.m3u8.mp4
2. /tmp/cat-video/https:%%link.to%playlist.m3u8.mp4
Additional information:
Conversion will occur in the background. Log files, output video
files, process pids will be saved to a file ".m3u82mp4.summary" in the
working directory where the script is executed.
EOF
}
while getopts "d:i:" optvar; do
case "$optvar" in
d) output_dir="$OPTARG" ;;
i)
has_input=1
input_paths=("${input_paths[@]}" "$OPTARG")
;;
*) show-help "$@" ;;
esac
done
shift $((OPTIND - 1))
if [[ "$has_input" == 0 ]]; then
show-help
builtin exit 1
fi
mkdir -p "$log_dir" "$output_dir"
for input in "${input_paths[@]}"; do
playlist-to-mp4 "$input"
done
if [[ -f $summary_file ]]; then
echo >&2 "stdout has been saved to $summary_file"
fi
# Author: Blurgy <[email protected]>
# Date: Jul 10 2021, 20:47 [CST]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment