I cannot believe I spent the better part of one day to fix a problem in many difficult ways when the fix was very simple!
What is ffplay
The FFmpeg project also provides a barebones media player known as ffplay
. It does not have any menus — main or context. You have to use certain keys and mouse actions for controlling the playback.
Keypress/ Mouse action | Function |
---|---|
SPACE bar | play or pause playback |
LEFT and RIGHT | fast-forward or rewind by 10 seconds |
UP and DOWN | fast-forward or rewind by 1 minute |
PAGE UP and PAGE DOWN | switch chapter (if present) if there are no chapters, behave like LEFT and RIGHT |
double-click | toggle between windowed and fullscreen view |
right-click | seek forward or backward using an invisible playback slider |
a | switch (audio) language |
t | switch subtitle (language) |
m | mute on/off |
/ | decrease sound volume |
* | increase sound volume |
w | switch filters |
Like ffmpeg
, ffplay
displays a huge banner and writes a lot of text messages on the console. You can hide them using some switches.
ffplay -hide_banner -nodisp -autoexit \
Nightfall-Stone-Ship.mp3
Even with this arrangement, ffplay
is not entirely quiet because it also writes to standard error. If you want a clean console, try
ffplay -loglevel quiet \
Nightfall-Stone-Ship.mp3
How to play videos with ffplay
As mentioned in another blog post, I now I use ffplay
command to fix two prominent problems with online videos.
- Extremely pale videos.
- Extremely loud or low-volume videos.
I use a Caja Actions Configuration to right-click videos and launch them with ffplay
. It has the effect of running this script manually.
bash play-with-ffplay-compressor.txt \
hobonichi-no-kaidan.mp4
Of course, to use Caja Actions, you should have chosen the Mate desktop. If you had meekly accepted Gnome 3 like a moron when it was imposed on you, then you deserve it. Free software is about freedom, is it not, slave?
The definitive ffplay
command for offline videos
The code in the play-with-ffplay-compressor.txt
script is as follows:
#! /bin/bash
# play-with-ffplay-compressor.txt
sFile=$*
sTitle=$(basename "${sFile}")
sSdata=$(ffprobe -loglevel quiet -print_format "default=nw=1:nk=1" \
-select_streams v:0 \
-show_entries "stream=width,height,duration" \
-i ${sFile})
sDur=$(echo $sSdata | cut -d " " -f3)
sWidth=$(echo $sSdata | cut -d " " -f1)
sHeight=$(echo $sSdata | cut -d " " -f2)
if [ "$sDur" = "N/A" ]; then
sDur=$(ffprobe -loglevel quiet -print_format "default=nw=1:nk=1" \
-select_streams v:0 \
-show_entries "stream_tags=duration" \
-i "${sFile}")
if [ -z "${sDur}" ]; then
notify-send "FFplay compressor" "Duration stream information not found"
echo "FFplay compressor: Duration stream information not found"
exit
else
sDur=${sDur%.*}
iMin=$(echo $sDur | cut -d ":" -f2)
iHour=$(echo $sDur | cut -d ":" -f1)
iSec=$(echo $sDur | cut -d ":" -f3)
let iHour=iHour*60*60
let iMin=iMin*60
let iDur=iHour+iMin+iSec
#echo $iDur $iHour $iMin $iSec
fi
else
iDur=${sDur%.*}
fi
iSubtitleCount=$(ffprobe -loglevel 0 -print_format "default=nw=1:nk=1" -show_entries stream=codec_type "${sFile}" | grep subtitle | wc -l)
if [ $iSubtitleCount -gt 0 ]; then
sSubtitlesFilter=",subtitles=filename=${sFile}"
else
sSubtitlesFilter=""
fi
ffplay \
-x 600 -y 337 -left 200 -top 200 -hide_banner -autoexit \
-window_title "$sTitle" \
-vf "eq=saturation=1.6,
drawtext=x=round((W-tw)/2):y=H-th-20:
fontfile='${HOME}/.fonts/Time-Normal.ttf':
fontsize=round(H/30):fontcolor=FFFFFF77:
text=\'%{eif\:mod(${iDur}/3600\,60)\:d\:2}\:%{eif\:mod(${iDur}/60\,60)\:d\:2}\:%{eif\:mod(${iDur}\,60)\:d\:2} ${sWidth}×${sHeight}\':
enable=lt(t\,15),
drawtext=x=round(W*t/${iDur}):y=H-th-1:
fontfile='${HOME}/.fonts/Inter-Regular.ttf':
fontsize=round(H/20):fontcolor=FFAABBDD:
text='□',
drawtext=x=W-tw-20:y=H-th-20:
fontfile='${HOME}/.fonts/Time-Normal.ttf':
fontsize=round(H/30):fontcolor=FFFFFF77:
text='%{eif\:mod(t/3600\,60)\:d\:2}\:%{eif\:mod(t/60\,60)\:d\:2}\:%{eif\:mod(t\,60)\:d\:2}'
${sSubtitlesFilter}" \
-af "dynaudnorm=gausssize=3" \
"${sFile}"
You can play a video with the above script like this:
bash play-with-ffplay-compressor.txt hobonichi-no-kaidan.mp4
The script writes some text, a square box, which moves to the bottom-left corner of the video which then moves to the bottom-right corner as the playback progress towards the end. Another piece of text is drawn for the timer in the bottom-right corner. In the middle, also near the bottom edge, some text is written for the total duration and dimensions of the video. This disappears after a few seconds.
The timer can also be set using the filter options timecode=\'00\:00\:00\:00\':timecode_rate=24
. This however includes the microseconds. That is overkill. For less distraction and more flexibility, I used three expressions (involving the t
variable, which stands for playback position in seconds) expanded in the text
filter option.
All day, I was trying to find a way to get the total duration of the playback in various filters to no avail. Eventually, it fixed it using ffprobe
in another bash
command.
This kind of fix is okay for amateur videos (that you find on TheyTube and Rumble) and bootleg videos. Do not use it for original movies or music videos.
Video demo
In ffplay
, you can right-click anywhere on the video as the entire frame acts as a giant progress bar.
Make the scrollbar permanent
If you want to permanently add the slider to your video, you need to make some modifications to the script.
#! /bin/bash
# add-scrollbar-to-video.txt
sFile=$*
sDuration=$(ffprobe -loglevel quiet -print_format "default=nw=1:nk=1" \
-select_streams v:0 \
-show_entries "stream=duration" \
-i ${sFile})
iDuration=${sDuration%.*}
ffmpeg -i "$sFile" \
-vf "drawtext=x=round(W*t/${iDuration}):y=H-th-1:
fontfile='${HOME}/.fonts/ttf-misc/Inter-Regular.ttf':
fontsize=round(H/20):fontcolor=FFAAEE:
text='□'" \
-af "extrastereo=c=0" \
-c:v libx264 -profile:v high -crf 21 -preset medium -tune film -r 25 -pix_fmt yuv420p \
-c:a libfdk_aac -vbr 5 \
"${sFile%.*}-SCROLLS.mp4"
When I play this ‘SCROLLS’ video with my ffplay
compressor script, the two squares (progress indicators) coincide!
How to play livestreamed videos using ffplay
Youtube-DL is under DMCA takedown. In its place, you can use its fork yt-dlp
.
To play livestreamed videos, you can use this script:
#! /bin/bash
# play-livestream-video.txt
sURL="$*"
sTitle=$(yt-dlp_linux --quiet --skip-download --print title $sURL)
yt-dlp_linux -o - "$sURL" | \
ffplay -window_title "${sTitle}" \
-af "dynaudnorm=gausssize=3" \
-
Run it like this:
bash play-livestream-video.txt https://www.youtube.com/watch?v=nvXLt3ET9mE
Do note that the ytp-dlp
command writes to the standard input and the ffplay
reads from the standard input. So, do not omit the hyphens on either side of the pipe.
How to play Youtube videos offline using ffplay
For other videos that have been uploaded to the Web, the above script will be annoying because you cannot fast-forward or rewind. It would be better to download and then play the videos offline.
yt-dlp_linux \
-f "hasvid,hasaud,[height>=360]" -S "+height" \
-o '%(title)s.%(ext)s' \
--exec 'ffplay -autoexit -af "dynaudnorm=gausssize=3" {}' \
https://www.youtube.com/watch?v=rf4cz_xjgIg
- Streaming sites offer the same video in multiple formats, dimensions and quality. The
-f
option is for specifying the name for one of these download options. The names differ from video to video and platform to platform. Instead of specifying an explicit name, I can use some special keywords instead. The keywordshasvid,hasaud
ensures thatyt-dlp
chooses download options that have both video and audio streams. The value[height>=360]
ensures thatyt-dlp
downloads videos whose height equal or greater than 360 pixels. With the-S
option, I have ensured that the smallest video among those available with the-f
option is chosen for download first.yt-dlp
ignores other qualifying videos. Without the plus (+
) prefix in its value,yt-dlp
would have chosen the biggest available video. - The
-o
option is for naming the download file. It uses some metadata placeholders. - The
--exec
option is for launching the downloaded video with some application. Obviously, I have chosenffplay
. The '{}' in theexec
option will be replaced by the downloaded video file name (including the extension).
Become an FFmpeg PRO by reading my book Quick Start Guide to FFmpeg.
- MORE INFO — http://www.vsubhash.in/ffmpeg-book.html
- BUY — https://books2read.com/ffmpeg (common link for all stores)
This post was updated to change the scrollbar text and to add the timer and subtitles.