bitreich-tv

meme tv encoding and streaming
git clone git://src.adamsgaard.dk/bitreich-tv
Log | Files | Refs Back to index

brtv-start.sh (4212B)


      1 #!/bin/sh
      2 # generate title animations and start streaming to server
      3 # requirements: ffmpeg(1), convert(1)
      4 
      5 ### CONFIGURATION START
      6 
      7 # intermediate playlist file
      8 playlist="playlist_$(date +%Y-%m-%d)"
      9 
     10 # memecache source dir
     11 memecache="$1"
     12 
     13 # converted memecache dir
     14 memecache_conv="memecache_conv"
     15 
     16 # title animations dir
     17 title="title"
     18 
     19 # ffmpeg flags for generated videos
     20 video_ext="webm"
     21 ffmpeg_codec="-loglevel error -acodec libopus -b:a 96K -vcodec libvpx -b:v 64k -f webm -vf scale=1280:-1 -r 30 -ac 2"
     22 out_video="brtv_$(date +%Y-%m-%d).${video_ext}"
     23 #out_video_duration="24:00:00"
     24 out_video_duration="00:05:00"
     25 
     26 # target video resolution
     27 video_resolution=1280x720
     28 
     29 # slide style
     30 bgcolor=magenta
     31 fcolor=white
     32 
     33 # show image memes for this duration [s]
     34 image_display_time=10
     35 
     36 # show title slides for this duration [s]
     37 title_display_time=5
     38 
     39 ### CONFIGURATION END
     40 
     41 pass="$(gpg2 -q -d icecastpass.gpg)"
     42 
     43 die() {
     44 	printf '%s: error: %s\n' "${0##*/}" "$1" >&2
     45 	exit 1
     46 }
     47 
     48 regeximatch() {
     49 	printf '%s' "$1" | grep -iEq "$2"
     50 }
     51 
     52 if [ $# -ne 1 ]; then
     53 	die "usage: ${0##*/} <memecache_path>"
     54 fi
     55 
     56 fit_img_16_9() {
     57 	convert -resize "$video_resolution"\> -size "$video_resolution" "$1" \
     58 		xc:"$bgcolor" +swap -gravity center -composite "$2"
     59 }
     60 
     61 video_from_img() {
     62 	printf 'image to video %s -> %s\n' "$1" "$2"
     63 	ffmpeg -y \
     64 		-f lavfi \
     65 		-i anullsrc=r=48000 \
     66 		-i "$1" \
     67 		-t "${image_display_time}" \
     68 		$ffmpeg_codec \
     69 		"$2";
     70 }
     71 
     72 title_slide() {
     73 	img="$(basename "${1%.*}".png)"
     74 	printf 'title_slide %s -> %s\n' "$1" "$img"
     75 	convert -size "$video_resolution" "xc:${bgcolor}" \
     76 		-pointsize 48 -fill "$fgcolor" \
     77 		-gravity center -draw "text 0,0 '#${img%.*}'" "$img"
     78 	ffmpeg -y \
     79 		-f lavfi \
     80 		-i anullsrc=r=48000 \
     81 		-i "$img" \
     82 		-t "${title_display_time}" \
     83 		$ffmpeg_codec \
     84 		"$2" && rm "$img"
     85 }
     86 
     87 video_conv() {
     88 	printf 'encode %s -> %s\n' "$1" "$2"
     89 	if ! regeximatch "$(file -ib "$f")" "^video\/"; then
     90 		die "input video $1 is invalid ($(file -b "$1"))"
     91 	fi
     92 	ffmpeg -y -i "$1" $ffmpeg_codec "$2"
     93 }
     94 
     95 mkdir -p "$title"
     96 mkdir -p "$memecache_conv"
     97 
     98 # generate video from each image
     99 for f in "$memecache"/*.jpg \
    100 	"$memecache"/*.jpeg \
    101 	"$memecache"/*.JPG \
    102 	"$memecache"/*.png \
    103 	"$memecache"/*.PNG; do
    104 	out="${memecache_conv}/$(basename "${f%.*}.${video_ext}")"
    105 	if [ ! -f "$out" ]; then
    106 		if ! regeximatch "$(file -ib "$f")" "^image\/"; then
    107 			die "input image $f is invalid ($(file -b "$f"))"
    108 		fi
    109 		printf 'in: %s, out: %s\n' "$f" "$out"
    110 		fit_img_16_9 "$f" "${out%.*}.jpg"
    111 		video_from_img "${out%.${video_ext}}.jpg" "${out}"
    112 	fi
    113 done
    114 
    115 # make animation for fallback stream
    116 if [ ! -f "bitreich-tv.${video_ext}" ]; then
    117 	title_slide bitreich-tv bitreich-tv.${video_ext}
    118 fi
    119 
    120 # make title slides for video and converted images and encode all video clips to common codec
    121 for f in "$memecache"/*.mkv \
    122          "$memecache"/*.mp4 \
    123 		 "$memecache"/*.webm \
    124 		 "$memecache_conv"/*."${video_ext}"; do
    125 
    126 	title_path="${title}/$(basename "${f%.*}.${video_ext}")"
    127 	[ ! -f "$title_path" ] && title_slide "$f" "$title_path"
    128 
    129 	out="${memecache_conv}/$(basename "${f%.*}.${video_ext}")"
    130 	[ ! -f "$out" ] && video_conv "$f" "$out"
    131 done
    132 
    133 # generate random playlist from converted memes and add title slides
    134 find "$memecache_conv" -maxdepth 1 -name "*.webm" -type f | \
    135 	sort -R | \
    136 	awk -v memecachedir="$memecache" -v titledir="$title" '
    137 	function add_title(s) {
    138 		sub(/memecache/, "title", s);
    139 		return s
    140 	}
    141 	{line=$0;
    142 	print "file \""add_title($line)"\"";
    143 	print "file \""$0"\""}' | sed "s/\"/'/g" > "$playlist"
    144 
    145 #printf '\nstarting fallback stream\n'
    146 #ffmpeg -loglevel quiet \
    147 #	-stream_loop -1 -i bitreich-tv.webm
    148 #	-f webm -codec copy
    149 #	icecast://source:${pass}@localhost:8000/brtvfallback
    150 
    151 
    152 # encode daily video file
    153 ffmpeg -n -f concat -safe 0 -i "$playlist" \
    154 	-f "${video_ext}" -cluster_size_limit 2M -cluster_time_limit 5100 -content_type video/webm \
    155 	-codec copy \
    156 	-to "$out_video_duration" 
    157 	"$video_out"
    158 
    159 printf '\nstarting stream\n'
    160 
    161 ffmpeg -f concat -safe 0 -stream_loop -1 -i "$video_out" \
    162 	-f webm -cluster_size_limit 2M -cluster_time_limit 5100 -content_type video/webm \
    163 	-analyzeduration 2M -probesize 2M \
    164 	-codec copy \
    165 	-deadline realtime -threads 4 \
    166 	icecast://source:${pass}@adamsgaard.dk:3232/brtv