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