FFmpeg: Rainbow trail chromakey effect


An effect loosely inspired by old Scanimate¹ analogue video effects. The process involves stacking progressively delayed, and colourised, instances of the input video on top of each other. These overlays are blended based on a chosen colourkey, or chromakey. The colour values and number of repetitions can be easily changed, though with higher numbers [in test cases, 40+], buffer underflows may be experienced.

#!/bin/bash

# Generate ['Scanimate' inspired] rainbow trail video effect with FFmpeg
# (N.B. Resource intensive - consider multiple passes for longer trails) 
# version: 2017.08.08.13.47.31
# source: http://oioiiooixiii.blogspot.com

function rainbowFilter() #1:delay 2:keytype 3:color 4:sim val 5:blend 6:loop num
{
   local delay="PTS+${1:-0.1}/TB" # Set delay between video instances
   local keyType="${2:-colorkey}" # Select between 'colorkey' and 'chromakey'
   local key="0x${3:-000000}"     # 'key colour
   local chromaSim="${4:-0.1}"    # 'key similarity level
   local chromaBlend="${5:-0.4}"  # 'key blending level
   local colourReset="colorchannelmixer=2:2:2:2:0:0:0:0:0:0:0:0:0:0:0:0
                     ,smartblur"
   # Reset colour after each colour change (stops colours heading to black)
   # 'smartblur' to soften edges caused by setting colours to white

   # Array of rainbow colours. Ideally, this could be generated algorithmically
   local colours=(
      "2:0:0:0:0:0:0:0:2:0:0:0:0:0:0:0" "0.5:0:0:0:0:0:0:0:2:0:0:0:0:0:0:0"
      "0:0:0:0:0:0:0:0:2:0:0:0:0:0:0:0" "0:0:0:0:2:0:0:0:0:0:0:0:0:0:0:0"
      "2:0:0:0:2:0:0:0:0:0:0:0:0:0:0:0" "2:0:0:0:0.5:0:0:0:0:0:0:0:0:0:0:0"
      "2:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0"
   )

   # Generate body of filtergraph (default: 7 loops. Also, colour choice mod 7)
   for (( i=0;i<${6:-7};i++ ))
   {
      local filter=" $filter
                     [a]$colourReset,
                        colorchannelmixer=${colours[$((i%7))]},
                        setpts=$delay,
                        split[a][c];
                     [b]colorkey=${key}:${chromaSim}:${chromaBlend}[b];
                     [c][b]overlay[b];"
   }
   printf "split [a][b];${filter}[a][b]overlay"
}

ffmpeg -i "$1" -vf "$(rainbowFilter)" -c:v huffyuv "${1}_rainbow.avi"
download: ffmpeg_rainbow-trail.sh

This is a top-down approach to building the effect. Another [possibly better] solution is to build the layers from the bottom up (pre-calculate the PTS delay for each layer i.e. "layer number x PTS delay"). This might improve the fidelity of the top layer in certain videos. Another idea is split input into three instances rather than two, and 'key overlay the third at the very end of the filter.


A concatenation of all videos generated during testing and development.

¹ Scanimate video synthesizer: http://scanimate.com/
original video: https://www.youtube.com/watch?v=god7hAPv8f0

FFmpeg: Extract section of video using MPV screen-shots



An unorthodox, but simple and effective way of accurately extracting a section of video from a larger video file, using MPV screen-shots (with specific file naming scheme) for 'in' and 'out' points.

Bash commands below serve only to demonstrate the general idea. No error handling whatsoever.
#!/bin/bash
# Extract section of video using time-codes taken from MPV screen-shots
# Requires specific MPV screen-shot naming scheme: screenshot-template="%f__%P"
# N.B. Skeleton script demonstrating basic operation

filename="$(ls -1 *.jpg | head -1)"
startTime="$(cut -d. -f-2 <<< "${filename#*__}")"
filename="${filename%__*}"
endTime="$(cut -d_ -f3 <<<"$(ls -1 *.jpg | tail -1)" | cut -d. -f-2)"
ffmpeg \
   -i "$filename" \
   -ss "$startTime" \
   -to "$endTime" \
   "EDIT__${filename}__${startTime}-${endTime}.${filename#*.}"
Another approach to this (and perhaps more sensible) is to script it all through MPV itself. However, that ties the technique down to MPV, whereas, this 'screen-shot' idea allows it to be used with other media players offering timestamps in the filename. Also, it's a little more tangible: you can create a series of screen-shots and later decide which ones are timed better.

video shown in demo: “The Magic of Ballet With Alan and Monica Loughman" DVD (2005)

FFmpeg: Simple video editor with Zenity front-end


A proof-of-concept implementation of a simple, but extensible, video editor, based on FFmpeg with a Zenity interface. Presented as a proof-of-concept as bugs still remain and the project is abandoned.

The goal was to create a video editor with the simplest of requirements; tools found on most popular GNU/Linux distributions, with a standard installation of FFmpeg (+FFplay). The original idea was to create just a video clipping tool, however, the facility to add functionality was included. Extending the functionality involved creating separate scripts with Zenity dialogs relating to the feature added.

While the effectiveness of the implementation is questionable, some interesting concepts remain, such as: a scrub-bar for FFplay created from just a set of filterchains, a novel approach to referencing time-stamps from FFplay, and the correct FFmpeg switches to force edit video clips on non-keyframes (the results of which are demonstrated in the video above).

download: ZenityVideoEditor_0.1.tar.gz

original version: 2016, 15th February https://twitter.com/oioiiooixiii/status/699239047806500864

Filthy Frank: "Pinku Dragon"


The effect was created by first extracting the foreground in Flowblade video editor [the FFmpeg version of this process was demonstraited previously¹]


In the animation, the Flowblade window is shown. The blur amount of a filter on the mask is being altered, which demonstraits the mask area growing and shrinking, and the edges of the mask get fuzzier.

Each cut-out frame was then sequentially merged, and overlayed on a background frame, creating the final animation. However, this was not the original goal of the process. If it were, it may have been easier to create using ImageMagick's stacking functionality²

[ Demonstrating the full procedure involved in foreground extraction using Flowblade may appear in a future blog post ]
¹ see also: https://oioiiooixiii.blogspot.com/2016/09/ffmpeg-extract-foreground-moving.html
² see also: https://oioiiooixiii.blogspot.com/2017/01/long-exposure-photography-compared-to.html
source video: https://www.youtube.com/watch?v=S6bQibFNs2E
original upload: (Twitter) August 5, 2016

Deceptive 2002 'Denny' Euro conversion calculator



Bash: Youtube-dl script which adds channel-id to video filenames

#!/bin/bash
################################################################################
# Download YouTube video, adding 'channel ID' to downloaded video filename¹
# - Arguments: YouTube URL
# source: htpps://oioiiooixiii.blogspot.com
# version: 2017.08.05.22.50.15
################################################################################

# Checks if video already exists in folder (checks YouTube ID in filename)
[ -f *"${1##*=}.mp4"* ] \
   && echo "*** FILE ALREADY EXISTS - ${1##*=} ***" \
   && exit

# Download html source of YouTube video webpage
html="$(wget -qO- "$1")"

# Extract YouTube channel ID from html source
channelID="$(grep channelId <<<"$html" \
            | tr \" \\n \
            | grep -E UC[-_A-Za-z0-9]{21}[AQgw])"

# Download best (MP4) version of YouTube video
youtube-dl -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best' \
            --add-metadata \
            "$1"

# Get filename of video created by youtube-dl
filename="$(find . -maxdepth 1 -name "*${1##*=}.mp4" \
            | cut -d\/ -f2)"

# Rename filename
echo "Renaming file to: ${channelID}_${filename}"
mv "$filename" "${channelID}_${filename}"

### NOTES ######################################################################

# ¹2017, May 21: Waiting for this to be implemented in youtube-dl
# youtube-dl -v -f137+140 -o '%(channel_id)s-%(title)s-%(id)s.%(ext)s'
# https://github.com/rg3/youtube-dl/issues/9676
download: ytdl.sh
context: https://github.com/rg3/youtube-dl/issues/9676

【中森明菜】:『少女A』(Akina Nakamori: "Girl A") - 1982, November 25th


source video: https://www.youtube.com/watch?v=kO2meEexNsE