Last active
February 8, 2021 20:02
-
-
Save bertm/69b05cac7ae2121ed700 to your computer and use it in GitHub Desktop.
Freenet M3U8 video stream generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This script uses x264 and ffmpeg to recode an input video to low-bitrate MPEG-TS segmented h264 | |
# stream that is suitable for streaming over the web and can be inserted into Freenet. | |
# Settings have been chosen to strongly prefer quality over encoding speed under conditions of an | |
# extremely low bitrate, to make the result suitable for direct streaming over Freenet. | |
# | |
# (c) bertm, 2014 | |
# | |
# Prefix for file names in the playlist | |
# Replace the SSK placeholder below with the proper destination SSK (empty for non-Freenet use) | |
PRE="http://localhost:8888/SSK@replace-me-with-a-proper-ssk-key/and-meta-dir/" | |
# Postfix for file names in the playlist (empty for non-Freenet use) | |
POST="?forcedownload=true" | |
# Input file | |
INFILE=big_buck_bunny_480p_stereo.ogg | |
# Output directory (playlist.m3u8 and segmentXXXX.ts are placed there) | |
OUTDIR=output | |
# Output video bitrate (in kbit/s) | |
VIDEO_KBITRATE=252 | |
# Output audio bitrate (in kbit/s) | |
AUDIO_KBITRATE=48 | |
# Output audio sample rate (in kHz) | |
AUDIO_KSAMPRATE=32 | |
mkdir -p "$OUTDIR" || exit 1 | |
rm -f "$OUTDIR/"segment????.ts | |
frate=$(($(ffprobe -print_format compact -show_streams -- "$INFILE" 2>/dev/null \ | |
| grep "|codec_type=video" | sed -n 's/^stream.*|r_frame_rate=\([0-9\/]\+\).*/\1/p'))) | |
if [ $frate -gt 24 ] | |
then | |
int=250 | |
else | |
int=$(($frate * 10)) | |
fi | |
video=$(tempfile).mp4 | |
stats=$(tempfile).log | |
function cleanup_x264() { | |
rm "$video" "$stats" | |
} | |
function fail_x264() { | |
cleanup_x264 | |
exit 1 | |
} | |
echo "Encoding [PASS 1/2]" | |
x264 --preset veryslow --bitrate $VIDEO_KBITRATE --aq-mode 2 --level 4.2 --keyint $int \ | |
--min-keyint $int --no-scenecut --vbv-maxrate $(($VIDEO_KBITRATE * 11 / 10)) \ | |
--vbv-bufsize $VIDEO_KBITRATE --no-fast-pskip --slow-firstpass --pass 1 \ | |
--output "$video" --stats "$stats" --log-level warning "$INFILE" || fail_x264 | |
echo "Encoding [PASS 2/2]" | |
x264 --preset veryslow --bitrate $VIDEO_KBITRATE --aq-mode 2 --level 4.2 --keyint $int \ | |
--min-keyint $int --no-scenecut --vbv-maxrate $(($VIDEO_KBITRATE * 11 / 10)) \ | |
--vbv-bufsize $VIDEO_KBITRATE --no-fast-pskip --slow-firstpass --pass 2 \ | |
--output "$video" --stats "$stats" --log-level warning "$INFILE" || fail_x264 | |
echo "Encoding [SEGMENT]" | |
ffmpeg -i "$INFILE" -i "$video" -map 1:0 -map 0:1 -c:v copy -c:a aac -ab ${AUDIO_KBITRATE}k \ | |
-ar ${AUDIO_KSAMPRATE}k -strict experimental -f segment -segment_time 10 \ | |
-segment_format mpegts -bsf:v h264_mp4toannexb -v warning "$OUTDIR/"segment%04d.ts \ | |
|| fail_x264 | |
cleanup_x264 | |
playlist=playlist.m3u8 | |
cd "$OUTDIR" | |
echo "#EXTM3U" > "$playlist" | |
echo "#EXT-X-VERSION:3" >> "$playlist" | |
echo "#EXT-X-ALLOW-CACHE:YES" >> "$playlist" | |
echo "#EXT-X-PLAYLIST-TYPE:VOD" >> "$playlist" | |
probes=$(tempfile) | |
for file in segment????.ts | |
do | |
ffprobe -print_format compact -show_format -- "$file" 2>/dev/null \ | |
| sed -n 's/^format.*|filename=\([^|]\+\).*|duration=\([^|]*\).*/\1|\2/p' >> "$probes" | |
done | |
echo -n "#EXT-X-TARGETDURATION:" >> "$playlist" | |
awk -F\| -- 'BEGIN { max = 0 } { if ($2 > max) { max = $2 } } END { print int(max + 0.5) }' \ | |
"$probes" >> "$playlist" | |
awk -F\| -v pre="$PRE" -v post="$POST" -- '{ print "#EXTINF:" $2 ","; print pre $1 post }' \ | |
"$probes" >> "$playlist" | |
echo "#EXT-X-ENDLIST" >> "$playlist" | |
rm "$probes" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment