DASH - Adaptive H.264 Videos erstellen
Skript zur Generierung von DASH-Videos, die je nach zur Verfügung stehenden Bandbreite das qualitativ beste Video dem Client bereitstellen.
brew install MP4box
brew install ffmpeg
#!/usr/bin/env bash
set -e
SAVEDIR="$(pwd)/"
mkdir -p "${SAVEDIR}"
renderAudio() {
filename="$1"
bitrate="$2"
if [ ! -f "${filename}_audio_${bitrate}.m4a" ]; then
ffmpeg -y -i "${inputfile}" -c:a aac -ac 2 -ab "${bitrate}k" -vn "${filename}_audio_${bitrate}.m4a"
fi
}
renderVideo() {
filename="$1"
bitrate="$2"
height="$3"
if [ ! -f "${filename}_${height}_${bitrate}.mp4" ]; then
# ffmpeg -y -i "${inputfile}" -an -c:v libx264 -x264opts 'keyint=25:min-keyint=25:no-scenecut' \
# -movflags frag_keyframe+empty_moov -g 25 -b:v ${bitrate}k -vf "scale=-2:${height}" -f mp4 -pass 1 -y /dev/null
ffmpeg -y -i "${inputfile}" -an -c:v libx264 -x264opts 'keyint=25:min-keyint=25:no-scenecut' \
-movflags frag_keyframe+empty_moov -g 25 -b:v ${bitrate}k -vf "scale=-2:${height}" -f mp4 "${filename}_${height}_${bitrate}.mp4"
fi
}
for inputfile in $@
do
fname=$(basename "${inputfile}") # fullname of the file
fname="${fname%.*}" # name without extension
echo "Converting \"${inputfile}\" to multi-bitrate video in MPEG-DASH"
renderAudio "${SAVEDIR}/${fname}" 96
renderAudio "${SAVEDIR}/${fname}" 48
renderVideo "${SAVEDIR}/${fname}" 1500 540
renderVideo "${SAVEDIR}/${fname}" 0500 540
renderVideo "${SAVEDIR}/${fname}" 0300 270
renderVideo "${SAVEDIR}/${fname}" 0200 180
ffmpeg -i "${SAVEDIR}/${fname}_540_0500.mp4" -i "${SAVEDIR}/${fname}_audio_96.m4a" \
-acodec copy -vcodec copy \
"${fname}_stream.mp4"
MP4Box -inter 500 "${fname}_stream.mp4"
MP4Box -dash 2000 -min-buffer 3000 -frag 2000 -rap -out "${fname}_mp4.mpd" \
"${SAVEDIR}/${fname}_540_1500.mp4" \
"${SAVEDIR}/${fname}_540_0500.mp4" \
"${SAVEDIR}/${fname}_270_0300.mp4" \
"${SAVEDIR}/${fname}_180_0200.mp4" \
"${SAVEDIR}/${fname}_audio_96.m4a" \
"${SAVEDIR}/${fname}_audio_48.m4a"
# "${SAVEDIR}/${fname}_360_0400.mp4"
# "${SAVEDIR}/${fname}_audio_32.m4a"
# rm "${SAVEDIR}/${fname}_540_1500.mp4" "${SAVEDIR}/${fname}_540_0500.mp4" \
# "${SAVEDIR}/${fname}_360_0400.mp4" "${SAVEDIR}/${fname}_270_0300.mp4" \
# "${SAVEDIR}/${fname}_180_0200.mp4" \
# "${SAVEDIR}/${fname}_audio_96.m4a" "${SAVEDIR}/${fname}_audio_48.m4a" "${SAVEDIR}/${fname}_audio_32.m4a"
done
Konvertieren via:
mp4-to-dash sample.mp4
Abspielen dann via dash-if player (Auszug aus dem _video.html.erb
-Renderer
einer Camaleon Instanz):
...
<script src="http://cdn.dashjs.org/latest/dash.all.min.js"></script>
...
<video data-dashjs-player id="video-<%= post.the_id %>"
poster="<%= post.the_thumb_url %>"
width="960" height="540"
controls="controls"
preload="auto"
data-src="/streams/<%= post.the_field('video-file') %>/<%= post.the_field('video-file') %>_mp4.mpd">
<source src="/streams/<%= post.the_field('video-file') %>/<%= post.the_field('video-file') %>_stream.mp4">
</video>
...
Da alle 2 Sekunden ein neues Fragment geladen wird, sollten im access-log vom nginx diese Requests ausgeblendet werden:
location /streams/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS, HEAD';
add_header 'Access-Control-Allow-Headers' 'range, content-type';
return 204;
}
access_log none;
add_header 'Access-Control-Allow-Origin' '*';
}
Die Konfiguration der Access-Control-Allow
-Flags kann entfallen, falls die Videos nicht von einer anderen URL
heraus aufgerufen werden.