Grabbing a single frame from a video using ffmpeg

Sometimes it is useful to just grab a single frame in a video for either promotional or debugging purposes. This command grabs a single frame, key things to note are:

-ss specifies the start time, note that at 25 fps a frame is every 00:00:00.040 seconds
-t as per the above this specifies capturing a duration of 1 frame

ffmpeg -i /tmp/a4ba54bfc77e5f50eea219e4f0e1b51a.mp4 -ss 00:00:14.68 -t 00:00:00.04 -f image2 singleframe2.jpg

Overlaying bitrate on adaptive bitrate streams for testing

Sometimes it is very useful if you don’t have full player control to see what bitrate stream is playing. To do this I have included a sample below of encoding to different rates.

Here I have selected mp4 as the output as it is usually fairly straight forward to re-segment an mp4 as DASH, HLS, Smooth etc and I will include some further examples on how to do that.

Here is a link to a simple shell script for creating the basic overlays on mp4 outputs: https://gist.github.com/sinkers/c4d39960018bca3540d4

Here is an example of taking the mp4 outputs and then fragmenting them with Bento and then packaging up as DASH: https://gist.github.com/sinkers/5cc2854e01a05a2db650

Here is an example of the result using DASH: http://mi9stuff.s3.amazonaws.com/overlay_dash2/manifest.mpd

And if you need it here is a sample DASH player: http://mi9stuff.s3.amazonaws.com/dash.js/

And here is the code for the :

#!/bin/sh
# encode_bitrate_overlay.sh
#
#
# Created by Andrew Sinclair on 11/07/2014.
#
#!/bin/bash
VIDSOURCE=$1
OUTNAME=$2
RESOLUTION1=”320×180″
RESOLUTION2=”512×288″
RESOLUTION3=”640×360″
RESOLUTION4=”960×540″
RESOLUTION5=”1024×576″
RESOLUTION6=”1280×720″
RESOLUTION7=”1920×1080″
BITRATE1=”400000″
BITRATE2=”800000″
BITRATE3=”1000000″
BITRATE4=”1200000″
BITRATE5=”1400000″
BITRATE6=”2000000″
BITRATE7=”4000000″
# Set this to a font file on your system
FONTFILE=”/opt/X11/share/fonts/TTF/Vera.ttf”
FONTSIZE=”40″
FONTCOLOR=”black”
echo “Encoding $VIDSOURCE”
AUDIO_OPTS=”-c:a libfdk_aac -b:a 160000 -ac 2″
AUDIO_OPTS2=”-c:a libfdk_aac -b:a 640000 -ac 2″
# Change the preset for better quality e.g. to slow or medium, ultrafast is just for testing the output quickly
# TODO add options for keyframe intervals for best adaptive segmentation
VIDEO_OPTS1=”-c:v libx264 -vprofile main -preset ultrafast”
VIDEO_OPTS2=”-c:v libx264 -vprofile main -preset ultrafast”
VIDEO_OPTS3=”-c:v libx264 -vprofile main -preset ultrafast”
OUTPUT_HLS=”-f mp4″
~/Desktop/workspace/ffmpeg-mac/FFmpeg/ffmpeg -i $VIDSOURCE -y \
$AUDIO_OPTS -vf “drawtext=fontfile=’${FONTFILE}’:text=’$RESOLUTION1 ${BITRATE1}bps’:fontsize=${FONTSIZE}:fontcolor=${FONTCOLOR}:x=100:y=100:box=1″ -s $RESOLUTION1 $VIDEO_OPTS1 -b:v $BITRATE1 $OUTPUT_HLS ${OUTNAME}_${BITRATE1}.mp4 \
$AUDIO_OPTS -vf “drawtext=fontfile=’${FONTFILE}’:text=’$RESOLUTION2 ${BITRATE2}bps’:fontsize=${FONTSIZE}:fontcolor=${FONTCOLOR}:x=100:y=100:box=1″ -s $RESOLUTION2 $VIDEO_OPTS2 -b:v $BITRATE2 $OUTPUT_HLS ${OUTNAME}_${BITRATE2}.mp4 \
$AUDIO_OPTS2 -vf “drawtext=fontfile=’${FONTFILE}’:text=’$RESOLUTION3 ${BITRATE3}bps’:fontsize=${FONTSIZE}:fontcolor=${FONTCOLOR}:x=100:y=100:box=1″ -s $RESOLUTION3 $VIDEO_OPTS3 -b:v $BITRATE3 $OUTPUT_HLS ${OUTNAME}_${BITRATE3}.mp4 \
$AUDIO_OPTS2 -vf “drawtext=fontfile=’${FONTFILE}’:text=’$RESOLUTION4 ${BITRATE4}bps’:fontsize=${FONTSIZE}:fontcolor=${FONTCOLOR}:x=100:y=100:box=1″ -s $RESOLUTION4 $VIDEO_OPTS3 -b:v $BITRATE4 $OUTPUT_HLS ${OUTNAME}_${BITRATE4}.mp4 \
$AUDIO_OPTS2 -vf “drawtext=fontfile=’${FONTFILE}’:text=’$RESOLUTION5 ${BITRATE5}bps’:fontsize=${FONTSIZE}:fontcolor=${FONTCOLOR}:x=100:y=100:box=1″ -s $RESOLUTION5 $VIDEO_OPTS3 -b:v $BITRATE5 $OUTPUT_HLS ${OUTNAME}_${BITRATE5}.mp4 \
$AUDIO_OPTS2 -vf “drawtext=fontfile=’${FONTFILE}’:text=’$RESOLUTION6 ${BITRATE6}bps’:fontsize=${FONTSIZE}:fontcolor=${FONTCOLOR}:x=100:y=100:box=1″ -s $RESOLUTION6 $VIDEO_OPTS3 -b:v $BITRATE6 $OUTPUT_HLS ${OUTNAME}_${BITRATE6}.mp4 \
$AUDIO_OPTS2 -vf “drawtext=fontfile=’${FONTFILE}’:text=’$RESOLUTION7 ${BITRATE7}bps’:fontsize=${FONTSIZE}:fontcolor=${FONTCOLOR}:x=100:y=100:box=1″ -s $RESOLUTION7 $VIDEO_OPTS3 -b:v $BITRATE7 $OUTPUT_HLS ${OUTNAME}_${BITRATE7}.mp4 \

Generating encodes and SMIL files for Akamai HD, Wowza etc

Here is a quick script I generated for encoding files and generating SMIL files for use with Akamai HD so they can be segmented on the fly as HDS or HLS.

Formatted etails here: https://gist.github.com/sinkers/148a39f8d926a443501a

or


#!/bin/bash
VIDSOURCE=$1
OUTNAME=$2
RESOLUTION1="320x180"
RESOLUTION2="512x288"
RESOLUTION3="640x360"
RESOLUTION4="960x540"
RESOLUTION5="1024x576"
RESOLUTION6="1280x720"
RESOLUTION7="1920x1080"
BITRATE1="400000"
BITRATE2="800000"
BITRATE3="1000000"
BITRATE4="1200000"
BITRATE5="1400000"
BITRATE6="2000000"
BITRATE7="4000000"

echo “Encoding $VIDSOURCE”

AUDIO_OPTS=”-c:a libfaac -b:a 160000 -ac 2″
AUDIO_OPTS2=”-c:a libfaac -b:a 640000 -ac 2″
VIDEO_OPTS1=”-c:v libx264 -vprofile main -preset slow”
VIDEO_OPTS2=”-c:v libx264 -vprofile main -preset slow”
VIDEO_OPTS3=”-c:v libx264 -vprofile main -preset slow”
OUTPUT_HLS=”-f mp4″

~/Desktop/workspace/ffmpeg-mac/FFmpeg/ffmpeg -i $VIDSOURCE -y \
$AUDIO_OPTS -s $RESOLUTION1 $VIDEO_OPTS1 -b:v $BITRATE1 $OUTPUT_HLS ${OUTNAME}_${BITRATE1}.mp4 \
$AUDIO_OPTS -s $RESOLUTION2 $VIDEO_OPTS2 -b:v $BITRATE2 $OUTPUT_HLS ${OUTNAME}_${BITRATE2}.mp4 \
$AUDIO_OPTS2 -s $RESOLUTION3 $VIDEO_OPTS3 -b:v $BITRATE3 $OUTPUT_HLS ${OUTNAME}_${BITRATE3}.mp4 \
$AUDIO_OPTS2 -s $RESOLUTION4 $VIDEO_OPTS3 -b:v $BITRATE4 $OUTPUT_HLS ${OUTNAME}_${BITRATE4}.mp4 \
$AUDIO_OPTS2 -s $RESOLUTION5 $VIDEO_OPTS3 -b:v $BITRATE5 $OUTPUT_HLS ${OUTNAME}_${BITRATE5}.mp4 \
$AUDIO_OPTS2 -s $RESOLUTION6 $VIDEO_OPTS3 -b:v $BITRATE6 $OUTPUT_HLS ${OUTNAME}_${BITRATE6}.mp4 \
$AUDIO_OPTS2 -s $RESOLUTION7 $VIDEO_OPTS3 -b:v $BITRATE7 $OUTPUT_HLS ${OUTNAME}_${BITRATE7}.mp4 \

MASTER=” \
\\
\
\
\
\
\
\
\
\
\
\
\
\

echo $MASTER > “$OUTNAME.smil”

 

CBR vs VBR in adaptive streaming

An interesting debate arose recently about whether CBR or VBR should be used when encoding for adaptive streaming. The debate started with my comment that adaptive streaming should use CBR as it better allows the client to manage what bandwidth it is receiving, the issue being VBR that if the client is receiving what it thinks is a 3Mbps stream that due to scene complexity then spikes say up to 6Mbps to deal with the extra complexity this would cause the clients buffers to fill a lot slower than expected for the bitrate and then down shift.

There are a few factors at play here in that need to be considered, these are:

  1. Real world bandwidth in a consumer environment available to a device can vary quite a lot
  2. Video encoding can demand varying amounts of bits to represent an image at a constant quality
  3. Encoding at a constant bit rate may produce video overhead from “stuffing” bits that unneccesarily consume storage and bandwidth

In relation to item 1. if we take a normal home environment not only the providers upstream available bandwidth may vary due to congestion but other in home factors come in to play such as competition for limited bandwidth from multiple downloaded to variations in single strength over wifi.

In relation to item 2. the amount of bits to encode 2 seconds of black vs a high action CGI scene with a lot of colours or rippling water is significant.

This post is a work in progress but if anyone is interested leave me a note and I will follow up.

Note that the Apple encoding recommendations for HLS which are widely cited refer to a maximum VBR rate of 10% over the target rate.

References:
Android Java based adaptive streaming client
Adaptive Video Streaming over HTTP with Dynamic Resource Estimation