FFmpeg: FAPA (Frame-Averaged Pixel Array)


Preamble: When I create a blog-post about a film, I will often include a cryptic looking pixelated image somewhere in the body of the post. When possible, I will create one of these images for every film I watch. I create them as a type of 'fingerprint', showing overall tonality and temporal dynamics of the film's visuals.

The image contains all frames in a given film. Each pixel represents the average colour of its particular frame. This colour is calculated by doing no more than scaling the frame to dimensions of '1x1' in a FFmpeg 'scale' filter. The frames [pixels] are then tiled into a single image of suitable dimensions.

The example video is taken from 'Summer in February (2013)' and shows a scene involving tropospheric lightening near the end of the film. The section of the 'pixel array' image relating to this scene has been highlighted and magnified. The contrast in lighting between frames means each frame can be clearly discerned as the video plays, even without the aid of the arrow.



The Bash script outputs basic information before and while processing. The process will take a reasonable length of time to finish. The version here uses two instances of FFmpeg to process the video. This is so progress feedback is displayed during execution. A simple single instance alternative is included in the 'Notes' section of the script, as well as ideas for showing progress while using this version. The script has not been updated since its initial creation and can probably be improved upon.

#!/bin/bash
################################################################################
# Create a 'Frame-Averaged Pixel Array' of a given video. Works by reducing
# each frame to a single pixel, and appending all frames into single image.
# - Takes: $1=Filename [$2=width]
# - Requires: ffmpeg + ffprobe
#   ver. 1.1 - 10th November, 2015
# source: https://oioiiooixiii.blogspot.com
###############################################################################

width="${2:-640}" # If no width given, set as 640
duration="$(ffprobe "$1" 2>&1 \
            | grep Duration \
            | awk  '{ print $2 }')"
seconds="$(echo $duration \
           | awk -F: '{ print ($1 * 3600) + ($2 * 60) + $3 }' \
           | cut -d '.' -f 1)"
fps="$(ffprobe "$1" 2>&1 \
       | sed -n 's/.*, \(.*\) fps,.*/\1/p' \
       | awk '{printf("%d\n",$1 + 0.5)}')"
frames="$(( seconds*fps ))"
height="$(( frames/width ))"
filters="tile=${width}x${height}"

clear
printf "$(pwd)/$1
___Duration: ${duration::-1}
____Seconds: $seconds
________FPS: $fps
_____Frames: $frames
_____Height: $height
____Filters: $filters\n"

# First instance of FFmpeg traverses the frames, the second concatenates them.
ffmpeg \
   -y \
   -i "$1" \
   -vf "scale=1:1" \
   -c:v png \
   -f image2pipe pipe:1 \
   -loglevel quiet \
   -stats \
| ffmpeg \
    -y \
    -i pipe:0 \
    -vf "$filters" \
    -loglevel quiet \
    "${1%.*}_$width".png

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

# Single line solution, but doesn't show progress
# ffmpeg -i "$1" -frames 1 -vf "$filters" "${1%.*}".png -y
# filters="scale=1:1,tile=${width}x${height}" # Used with single line version
# View ingest progress using: pv "$1" | piped to ffmpeg
download: video2pixarray.sh

[Note: I have struggled with giving a name to this process since I created the script, and have left it as the first thing I thought of. Perhaps others whom have creating something similar have better names for it.]

film review: https://oioiiooixiii.blogspot.com/2017/11/summer-in-february-2013.html

ANSI to HTML: Incorporating 'ansi2htm.sh', 'tiv', 'bat', 'GNU source-highlight', 'bash-drawille'

'tiv' [Terminal Image Viewer] with 'ansi2html.sh'
- Reproduce raster image in HTML unicode characters.


script -q /dev/null -c "tiv image.jpg" | ansi2html.sh > image.html
# output 'pre' tags refined with 'line-height' and 'font-size' styling 
N.B. Due to tag limits set for blog post content, this is only a screen capture representing the result. The actual html representation is demonstrated here: https://oioiiooixiii.blogspot.com/p/ansi2html.html


'bat', with 'ansi2html.sh'
- 'cat'-like application with additional syntax formatting and colouring.
   1 #!/bin/bash
   2 # An example Bash script
   3 # Version: 2018.08.19.19.33.05
   4
   5 function main() # An example function
   6 {
   7    local sentence="Hello, World!"
   8    for (( i=0;i<"${1:-1}";i++ ))
   9    {
  10       echo "$sentence"
  11    }
  12 }
  13 main "$@"
  14 exit

bat -n --color always --theme "1337" example.sh \
| ansi2html.sh --bg=dark > example.html

'bash-drawille' with 'ansi2html.sh'
- Convert raster image into Braille type HTML unicode characters.
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣿⢿⣿⣻⣿⣿⣿⣷⣿⣯⣿⣽⣿⡿⣿⣏⣿⣾⡿⣻⣽⣻⣯⣯⡿⣾⣳⡿⣯⣾⢿⢾⣟⡽⣯⣯⣹⣏⣯⣽⢯⡽⡯⣏⣗⡿⣺⢽⣝⢯⢽⡽⣳⢽⣞⣚⣞⠯⣗⢯⣖⡯⢯⡶⣏⣹⠶⢯⣚⣝⡼⣹⠶⣓⡧⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⡿⢿⣝⣟⣟⠯⠻⠝⢑⠹⠋⠹⠺⠿⠿⡿⣿⣝⣿⣟⣾⣻⣯⣽⣿⣽⣻⣽⣻⣿⣾⢿⣟⣿⣾⣻⣷⢿⣷⡿⣟⡽⣾⣷⣯⣹⣽⣹⣏⣟⣺⡷⣗⣻⣗⡷⣺⢽⢷⢽⢽⣝⢶⢽⣺⣹⢭⡯⡽⡽⣓⣞⣗⣞⠶⣏⣹⠾⣞⢭⡼⢧⣓⡽⣞⣱⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣿⡿⢯⢹⣩⣪⠪⢩⠍⠨⠰⠢⠐⠂⠀⠀⠀⠀⠐⠀⠁⠈⠊⠉⠟⡍⠞⠭⣻⡽⣿⣟⣷⣿⣽⣯⣟⣽⣟⣾⣻⣾⣳⣻⣽⢿⣾⣽⢷⣻⡷⣾⣷⣗⣻⣺⣗⣟⣺⣟⢾⢽⣺⡾⣺⣝⣞⣫⡯⡗⡷⡯⢽⣳⣺⢭⢷⣖⡽⢧⣏⣹⢳⡗⣏⢳⡞⣞⢭⡼⣚⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣏⡞⣭⠕⢙⡨⠊⡁⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠆⠆⡈⠹⢻⢷⢾⡿⢾⢿⣷⢿⣾⣻⣽⣻⣿⢾⣯⣗⣾⣯⣫⣻⡾⣷⣏⣽⣏⣯⣏⣯⢾⡷⡿⣺⢽⣏⣗⢷⣝⣗⢽⣞⣗⣳⣲⡽⣞⠯⣓⣞⢷⣚⢷⣚⢯⣚⣫⢳⣱⢷⢞⢭⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠓⣉⡝⣵⣕⠵⢊⢆⣌⢖⢈⢀⡀⢀⠀⠂⠄⠀⡀⠀⠂⠤⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠅⡀⠀⢪⡍⠏⠩⠝⠼⡻⡾⣽⣻⣽⣻⣟⣯⢷⡿⣯⣟⣝⣽⢷⣽⡷⣽⢷⡷⡯⣽⣺⣹⡷⣳⣳⣝⣟⡾⣺⡯⡶⣝⡾⣏⣏⢽⣺⡽⢭⣞⡞⢭⢷⡭⣳⣓⡽⡶⣏⢧⣫⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⡡⢒⢡⡯⣿⠏⡫⢖⠳⠕⡐⡰⡐⣂⠰⢐⠠⡢⢄⢌⡄⡐⠲⠅⡉⡢⡡⡠⡠⢆⠀⢀⠀⠀⠀⠡⠀⠀⠀⠤⢀⠀⠀⠁⠨⠋⢽⣳⣟⡽⣟⣾⢷⣟⢷⣿⢷⣟⣾⢯⣟⣞⣗⣻⡽⣽⣝⣯⢾⢽⣗⡯⡾⣺⡯⡾⣫⡷⣳⣣⣝⡾⡯⣗⣹⣺⠯⣳⢧⣳⡭⣳⠮⣗⣹⠶⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⠫⠔⢊⡚⡔⢕⠋⠡⣐⠆⢃⢔⢲⢊⡡⡩⣔⢦⢕⣕⡼⡭⢖⣅⡪⢕⡵⣏⡺⣪⠶⡵⢕⡕⠸⢣⢖⠦⠈⠈⠠⠀⠀⠀⠀⠢⢠⠀⠀⠈⠫⢾⡿⣷⡿⣯⣳⣿⡾⣯⣫⡷⣟⣾⡷⣟⣺⡷⡷⣗⣯⢽⣹⡷⡾⢯⡯⢽⣝⢷⢯⡽⡝⣫⢯⣜⡾⢽⢳⡧⣏⢯⣚⣹⡼⣹⠶⣫⢳⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⡛⠙⠑⡈⡂⠴⠪⢈⡉⣁⡨⢌⡑⡬⢜⣃⡥⡶⢮⣲⣷⣷⣿⢿⢾⡿⣺⣹⣹⢵⢮⣖⡯⣹⣹⢳⣪⡪⣂⠜⢯⢗⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠐⢯⢾⡿⣞⣯⡾⣯⣗⣽⣽⡷⣾⡷⣯⢽⢾⡷⡯⣽⢾⣏⣫⣟⢷⢽⢽⣝⣗⢷⣏⡯⣺⣹⡽⡭⣏⣏⣞⠯⣞⡞⣓⡽⣚⡽⣓⡽⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠢⠐⠈⠑⠑⠐⢐⢐⠂⠒⡌⢑⢌⢞⢕⢕⢪⣾⣯⣿⣿⣿⣿⣿⣿⣿⣳⣿⣾⣺⣻⣞⡽⣽⣽⢺⣺⠽⢼⡣⣆⠱⢎⠜⢂⠤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢺⣷⢯⣻⢷⣟⣟⣹⢾⣟⣾⡷⣯⢽⣏⣯⢽⡷⡯⣽⢷⢾⢯⡯⣺⣫⡯⡾⣝⣗⣗⠯⡯⢽⣹⢼⢽⣺⡼⢽⡽⢭⡭⣳⢳⡞⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠱⣕⣱⠧⡔⢐⠁⠈⡀⢠⢙⠪⣎⡱⣑⣲⢯⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣻⣟⣝⣗⣛⣗⡮⢞⡳⢞⠵⢮⡪⡔⠙⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⢽⣻⡾⣿⡷⣟⣞⢷⣯⢾⡷⢾⡯⣽⣺⣻⣹⡯⣗⣏⡯⡷⣽⢾⣝⣗⢷⣳⢽⣺⣫⢽⡭⡯⣗⡧⣗⣞⡝⣹⢼⢧⣳⠷⣫⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠯⢔⢱⠯⡉⠥⠱⠀⠈⡐⣊⡼⢽⡪⢎⢼⣽⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢾⣻⣫⡷⢷⡽⢭⣍⡗⡵⡩⡳⡪⢕⢃⠨⠈⡂⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢽⡾⣽⢾⣿⡾⣟⢿⣞⣽⢯⡷⣽⣯⢽⣽⣹⣗⡯⢷⡾⢯⢽⡽⣝⢷⢽⣗⣳⡾⣺⣳⡯⣺⣹⠽⣳⣹⣺⢷⣓⢯⢳⡞⣝⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣑⠮⠈⠘⠂⠒⠐⠠⡈⣎⡭⣳⡞⡨⣏⣽⣿⣿⣿⣿⣿⣿⡿⣿⣿⣷⣿⣿⣯⣫⣏⢷⣝⡼⢮⡱⣎⢎⡪⡎⡪⢎⢁⠅⡀⠂⢈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠰⢽⢽⣽⢯⣏⣻⣻⡷⣻⢾⡷⣟⢾⢾⣺⡷⣗⣻⡷⡷⡷⣻⢽⡽⣫⡷⣝⣗⣺⣫⢷⢯⣺⣓⣝⡾⢷⣓⢫⣳⣫⢳⡞⣏⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⡿⣗⣡⠀⠀⠀⡀⠆⠰⣕⡽⠮⣏⡪⣲⣻⣿⡿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣯⢿⡷⡿⣺⡼⡞⣪⣃⢝⣊⡪⠎⡪⠕⡂⢈⢐⢃⡈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢐⠪⡼⣟⣾⢷⣟⣝⡷⣟⡷⣟⢾⢷⣻⣹⡷⣻⢾⣗⣽⣫⣞⣞⢽⣝⢷⢽⣝⣗⣗⢷⡾⣝⢭⡯⣗⣳⡽⢭⡯⣏⡗⣏⣓⡾⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⣿⣿⡇⠀⠀⣐⢖⣃⣞⡷⣟⢿⢪⢮⡽⣿⣾⣟⣾⣿⣟⣟⣟⣫⣻⣻⣽⢽⣹⡷⣞⠽⣎⢮⡰⣍⢮⡪⡚⣑⢃⢘⢈⠄⠆⢒⡈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⢈⢊⢭⣟⡷⣯⣗⣯⣳⣟⡽⣯⢿⡾⡽⣽⡷⡷⣻⣹⣽⣹⣹⡷⡯⡽⣫⡯⣺⣫⣺⣓⣏⡯⣹⣹⣺⢼⣞⠯⣜⡽⣓⡾⡾⢭⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⠀⢑⠨⢾⢾⡿⢽⢝⢼⣽⣻⣯⣿⣷⣿⣿⣟⣿⡿⣽⣳⢿⡷⢽⡽⣹⡼⣣⢝⠮⡼⣣⢕⠎⡰⡘⣂⠍⡂⠡⠔⠰⠰⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⢎⢼⢽⢷⣟⡯⣻⣽⢾⣗⣽⣟⣺⢷⡷⡷⣯⢽⣺⣺⣹⣹⣗⣟⢾⣺⣫⢽⣝⢽⡭⢷⣫⣺⢼⣗⠯⢯⢯⢳⣳⡭⢷⣓⣞⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠀⠠⠌⠐⢞⣻⣟⡱⣏⣽⣟⣿⣟⣿⢿⣷⣟⣿⣻⣷⡿⣞⣽⣽⣽⣯⢷⣚⢮⣑⢎⡮⢎⢦⡵⡡⡱⠢⡈⢁⠄⢈⢁⠂⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⡪⡯⣿⡾⣟⣞⣽⢾⡯⣽⣯⢽⢾⡷⣯⢽⡽⡽⣻⣝⣫⡯⣗⢷⡽⣝⢷⢽⡯⡾⣗⢷⣏⡯⢽⣺⡽⡝⣗⣏⡗⣏⣞⢭⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⡐⢀⢈⡸⢽⣝⣜⡽⣿⣷⣿⣺⣿⡿⣿⡿⣿⣿⢿⣟⣹⢽⣷⡿⣝⡳⣩⠳⢱⡕⢱⡣⢗⡕⠕⡊⢡⢁⠐⡐⡀⠂⠁⡐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠌⢈⢽⣝⣽⡽⣷⢿⡷⢿⣞⣯⣹⡯⣟⣺⣗⣳⣳⣽⣫⣞⣗⣗⢷⣽⣣⢷⢽⢽⣞⣚⣗⣗⡯⡗⡷⡯⢽⣺⡼⣹⣺⡼⢯⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡢⣇⢆⠢⡡⢞⣚⡾⣽⣻⣿⣽⣿⣟⣻⣞⣗⡷⣺⢳⢝⠰⢺⢳⡗⢕⢍⢊⡢⣱⢪⠕⠎⠔⡰⠨⠆⠅⣈⠂⡈⠀⠐⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠅⠀⡄⣪⣏⣽⣯⣺⢷⣯⢿⣞⡽⣯⢾⡷⣏⣟⣺⢽⣽⣝⣹⡷⣺⣳⡾⢾⣝⣞⡯⡾⢽⡭⡽⣗⢽⣹⡽⡭⢷⣓⢯⣣⢳⡞⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣗⢞⡪⡪⡪⢞⢭⣻⣽⣿⡷⡽⣯⢿⡯⣻⠾⠣⠣⡐⠂⢸⢖⡈⠀⠈⠡⢉⢢⠅⠊⠲⠮⡁⠀⠀⠐⠀⠐⠄⠂⠁⢀⠂⢀⠂⠄⠠⠀⠀⠀⠀⡀⠀⠀⠀⠀⡂⠰⢬⢾⢷⣯⡯⣻⢿⣞⢾⡿⢾⡷⣗⣟⡾⡷⣻⣝⣺⣹⣹⣗⢽⣝⡷⡾⣽⡝⣫⡯⣳⢽⣞⢯⡽⣳⣹⣹⣗⣞⢳⣺⡽⢧⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣽⡾⣯⢎⢮⠯⡯⢾⣻⣏⣯⣾⡷⡵⢞⠴⠀⠀⠀⠄⠀⠜⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠁⠆⠄⢁⠀⠄⠀⠀⠀⠀⡀⠄⢁⠀⠀⠆⠆⢌⡯⣿⢯⣟⣝⣻⡿⢾⡿⣻⢾⣽⣹⡷⣻⢾⡯⣻⣝⢯⡯⡯⡽⣫⡯⡾⣺⢯⣞⡯⡽⣳⣣⣜⡾⢷⣓⣺⡼⢽⣲⢫⣳⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣷⡷⢵⡷⣏⡙⡹⠍⠗⠈⠀⠀⠀⠀⠀⠀⠀⠀⡀⣠⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢂⠂⠅⡀⠐⠈⠀⠈⠐⠀⠀⠀⠁⠀⢀⢄⢥⣲⡿⣽⢿⢾⣟⣾⣷⢷⣯⡷⣯⡷⣯⢽⡯⢾⡷⣝⣯⣝⣗⢽⡽⢷⢾⣫⡯⢽⣝⣗⣺⡽⡝⢫⢷⡾⡝⢷⣓⠯⣗⡗⣏⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣽⣿⡾⢮⠔⠅⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠨⣿⣿⣗⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⢐⠀⠀⠌⠠⠄⠂⠀⠀⠁⠁⠂⢐⠀⠀⠀⠄⠀⠐⢆⡯⡯⣽⡽⣽⢽⡷⣾⢷⣽⢯⣳⣟⢾⡷⣻⢾⣝⣯⣗⣯⢯⢯⣯⢾⢽⣝⡯⡾⡯⡽⡽⣗⢯⣞⣳⡯⣹⣺⣗⣞⠯⣏⢧⣏⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡯⢷⣇⡐⡠⡐⢄⠄⠀⠀⠀⠀⠀⠀⢀⣲⣿⣿⣿⡟⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⠐⢀⢂⠨⡂⠰⡀⠁⠀⡀⠀⠀⠀⡁⠀⠀⠀⠀⠀⠄⡲⣻⣺⣳⣷⢽⣯⢾⣺⣹⡯⣽⣟⣺⡷⣟⣽⢾⣏⣟⣏⣗⣟⣺⢾⣏⡯⡾⢽⣝⢽⣝⣺⣣⣳⡽⣺⢽⣳⣓⣺⡼⢯⣲⣫⢳⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢺⣯⣿⣿⣭⢕⠣⠄⠂⠀⠀⢀⢠⣸⣷⣿⣿⣏⡇⢁⠈⢒⠀⠀⠀⠀⠀⠀⠀⢀⠀⠠⢐⠢⠌⡁⠀⠂⠀⠈⠀⠁⠀⡀⠀⢀⠈⠀⠀⠀⣕⢾⢾⡯⡾⣺⣫⣺⣣⣳⢷⣞⣗⡯⡽⣻⣹⣺⣞⢾⡯⣻⣝⣹⡷⡯⡽⣫⣟⢷⢽⡯⡶⣫⡯⣏⣗⡯⣖⣞⡝⣳⣚⢷⣚⢯⣚⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣟⣻⣿⣿⣷⣆⣂⡄⡀⣰⣳⣾⡿⣯⣿⣿⣓⢇⠄⡈⠡⠆⢃⢂⠆⡂⠄⠅⡈⠡⠰⠐⠂⠠⠁⠀⠀⠀⠀⠀⠈⠀⠀⠄⠄⠐⠀⠀⠠⢺⣳⡷⣫⡯⣫⢯⣳⢷⣺⣓⣗⡯⣹⣹⣳⣫⣞⣞⡯⣽⡷⡷⡷⣽⡯⣽⢷⢽⣝⣗⢽⣹⢷⢯⢾⢼⡧⡷⡯⢯⢫⣳⢭⣳⡽⢭⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡭⣎⢫⡽⣿⢿⣿⢿⣧⣽⣷⡯⢿⢿⢾⣿⢽⡳⢮⡃⡀⠈⠀⠀⠖⢎⢔⢆⠆⡂⠁⠄⠠⠄⠀⠈⠀⠄⠀⠀⠀⠀⠐⠅⠀⠁⠐⠀⠀⢠⠯⠾⣺⡯⡾⡾⣺⣹⣹⡾⣝⠽⣳⡗⡯⣞⣺⣚⣗⣝⣗⢽⣺⣞⣗⣗⢷⡾⣺⡯⡾⡯⡾⣫⢷⣏⣏⣺⣹⢭⢯⡯⣏⡧⣏⣹⢺⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣖⡵⣱⢯⡯⣗⣷⣿⡷⢯⠍⠐⣹⢿⣿⢷⣞⠵⡃⠀⠀⠀⠀⠀⠀⢊⡩⢆⡃⠜⡂⠆⠠⠁⠀⠂⠀⠆⠀⠀⠠⠀⠀⠀⠀⢀⢐⠰⢵⢽⣝⣗⢷⢽⢯⣞⣜⣗⠽⣗⣹⣺⣲⡽⢯⣲⢳⣺⢳⢷⣝⣗⡷⣽⢽⣝⡯⡾⣫⡯⣫⢯⢾⢺⡧⡷⣏⣏⣞⠯⡼⡽⣖⡯⢧⣏⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣎⢳⡞⣗⣗⡯⡾⡎⠑⠁⠀⠠⢽⡹⣋⠽⠎⠕⠈⠀⠀⠀⠀⠀⠀⠀⠐⠁⠈⠁⠠⠈⡈⠀⠐⠠⢀⠀⠀⠀⠈⠀⠀⠁⡂⢱⢦⢵⢳⢷⣗⣺⣫⡯⣺⣹⢽⡭⡽⡾⣳⣓⣳⣚⢷⣓⠷⣏⡧⣏⡭⡯⡾⣺⡯⡽⣫⡯⡾⣺⢽⣝⡽⡾⢯⢽⣳⣚⢯⢯⡾⡭⣖⡽⣧⣯⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⡽⢎⡵⣏⢕⢎⠈⠀⠀⠀⠠⣌⠈⡈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⠈⠂⠀⠀⠀⠀⠀⠀⢨⣪⠽⣺⣣⣳⡽⣞⢯⢯⢯⣺⡼⣺⢽⡭⢯⣞⢭⡭⢯⡽⢭⢯⢳⣹⡲⢯⣚⣏⣏⡯⡾⣺⣫⡾⣺⣺⣫⢫⡯⣗⣳⢭⡯⣗⣺⢽⢺⣹⠽⡼⡽⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢮⢪⢗⠢⡃⠐⠁⠀⠀⢀⢼⢾⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠌⠀⠀⠀⠀⠀⢜⢷⣫⢭⡯⡽⣗⡯⣖⣞⣺⢯⣣⡯⢧⣫⢳⡞⣏⣹⢼⢧⣫⢗⡾⣓⡯⢳⡞⣲⡽⢽⣞⣗⢷⣺⣓⣝⣞⣳⡽⡗⡯⣏⣗⡧⣗⡯⢧⡽⢯⢳⡞⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣝⠰⡂⢈⠀⠀⠀⠨⢵⡷⡷⣽⣑⠄⠀⠀⠀⠀⠄⡀⠰⠂⢀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡉⠓⣝⡾⡯⣏⣞⠯⢷⣣⡽⡭⣞⡝⢯⣓⢯⢳⣞⠽⡼⢧⢳⡞⣞⢭⢯⣚⣝⢼⣺⢯⢯⢽⣫⢯⣗⣳⢯⢽⢾⢼⣹⣹⣚⡾⣳⣞⢳⣺⡯⢧⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡔⡡⠥⠀⠀⠀⡁⠂⠸⡹⣹⢻⣞⢆⠰⠄⠀⠂⠈⠐⠀⠀⠈⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣽⡧⠀⠘⢝⣺⢼⣹⣺⢭⢷⣹⢺⣞⠽⣞⡭⣏⡳⢗⣝⡳⡞⣏⡼⣹⠶⣍⣳⠶⡯⢧⣳⡽⣝⢾⢺⣺⢯⢭⢯⣏⣏⢯⣖⡾⡭⣖⡯⢽⣲⢫⣳⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣏⡒⢁⢂⣖⠂⠀⠀⠠⣀⣀⡈⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⣿⣿⡇⠀⠀⠸⣳⢧⣗⢯⣓⢯⢳⣺⠽⡼⢧⣏⡵⢧⣫⣓⡧⣫⢳⢧⣹⡼⢞⠽⡼⣹⠾⣜⡾⡯⣏⡗⣗⡯⢽⣺⢼⣺⢽⣜⡽⣹⡼⣞⠽⡼⢽⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆⠐⢱⢎⢂⠀⢀⢴⡭⣹⢳⡹⡫⡛⠕⠀⠀⠐⠀⠐⠀⠀⠄⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⣽⣿⣿⣷⠀⠀⠀⠀⠧⣫⢳⣳⢯⣚⣓⡽⡭⣳⠶⣏⣹⢖⡭⣳⡼⢧⣓⡵⡳⡞⣏⢳⣹⠾⣗⣺⣚⣗⡯⢽⣗⣺⢯⢳⢯⣲⡭⢷⣳⣚⣓⡽⢳⡞⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣄⠌⡑⠅⢸⡾⢷⢯⢞⡌⠌⡠⡈⠌⡀⠀⠀⠀⠀⠀⠀⡁⠠⠐⠀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢴⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠯⢧⣞⢭⡭⣳⠽⣜⡞⣕⣏⢳⡞⣕⡵⡞⡭⡞⡳⢧⡹⣜⢞⣹⣓⣞⡽⡭⣗⣺⣖⡽⡧⣷⠯⣳⣧⣯⣞⢭⣳⣿⣏⣽⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⡿⠗⠆⠐⠡⢪⢯⣽⣹⣷⣹⣯⣚⢎⡦⢆⢣⣂⢀⠂⠠⠰⠂⡀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⡓⠀⠀⠀⠀⠀⠀⠀⠀⠐⠫⡝⡲⢯⡹⡼⢞⡼⢮⣓⢧⡹⣎⣣⠯⡵⢞⡹⣎⢧⠯⣞⣞⠯⣗⣯⣶⣳⣷⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠻⠛⠋⠁⠁⠀⠀⠀⠀⠀⠀⠀⢪⢹⣫⣟⢽⡾⢫⢯⡺⡕⠯⡳⠮⡰⢂⠂⠈⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠙⠳⠮⣍⡞⡭⡞⣱⢫⣣⠽⢼⡹⢎⡵⡝⣖⢯⢽⣽⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠻⠟⠉⠉⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣍⠥⡪⢓⡫⡸⢝⢊⡪⠎⠣⠚⠂⠑⠁⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⡋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠓⠱⠋⢜⢧⡳⢞⡳⣩⠯⡼⣿⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠛⠁⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⡇⠀⠀⠀⡈⡐⠑⠄⢁⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠑⢝⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠃⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣇⠀⠀⠀⠀⠂⡂⢁⠨⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣾⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠁⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣬⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠨⢂⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣻⢿⣹⠶⢏⡽⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣿⣿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⡿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠈⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⣿⣿⣿⣿⣿⣿⣿⣿⣗⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣲⣿⣿⣿⣿⣿⣿⣿⢿⢺⢭⣓⢧⢯⡹⡵⡞⣏⡳⣧⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣻⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⣟⣿⣿⣿⣿⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⡫⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣽⣿⣿⣿⣿⣿⣿⣿⣿⣿⡽⢞⣍⣳⢳⢭⢝⡼⡞⣹⠶⣏⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⢿⣿⣿⣿⣿⣿⣹⣖⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣺⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣞⢭⠶⣏⢧⠯⢯⣚⡵⢧⣫⣿⣿⣽⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣾⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⣿⣿⣿⣿⣿⣿⣀⠕⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣻⢳⣿⣽⣽⣿⣿⣿⣿⡟⣍⣳⣯⣿⣿⣿⣿⣿⠀
⣿⣽⣿⣿⣯⣿⣿⣷⣿⣻⣿⣿⣿⣿⣿⣽⣯⣿⣿⣿⣿⣯⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⢼⣾⠎⣿⣿⣿⣿⣽⡪⣒⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠓⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⣿⢯⠽⣟⡼⡝⣶⣷⣿⣿⣿⣿⣿⠀
⣿⣿⣾⣿⣿⣿⣷⣿⣿⣿⢿⣿⢿⣿⣿⢿⣻⣿⣿⣯⣿⣽⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡸⣯⣽⣿⣻⣿⣹⣿⣿⣿⡕⡆⡀⠀⠠⠀⠂⢠⣼⣻⠽⣜⡝⡪⠜⡸⠟⢿⣿⣿⣿⣟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⢿⣿⣿⣻⣻⣿⣿⣿⣟⣿⣟⣿⣿⡿⣿⣿⣿⢿⣿⣿⢿⣿⠟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⣿⡔⠔⠄⢀⣵⡿⣺⣓⡯⡣⣃⢕⢕⢎⢔⢕⡻⢙⢛⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
⣿⣿⣿⣟⣟⣿⣟⣿⣿⣿⣻⣿⡿⣿⣿⣿⣾⣿⣷⣿⣿⡽⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡂⠸⣿⣷⣷⡯⡳⢕⢪⢮⣵⣺⣾⡾⣮⣧⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀
convert-image.sh | ansi2html.sh > braille.html
# output 'pre' tags refined with 'line-height' and 'font-size' styling 


GNU 'source-highlight'
- Print source files [e.g. Bash scripts] with colour syntax highlighting.
01: #!/bin/bash
02: # An example Bash script
03: # Version: 2018.08.19.19.33.05
04:
05: function main() # An example function
06: {
07:    local sentence="Hello, World!"
08:    for (( i=0;i<"${1:-1}";i++ ))
09:    {
10:       echo "$sentence"
11:    }
12: }
13: main "$@"
14: exit
source-highlight -n -f html -i example.sh -o example.html

ansi2html: https://github.com/ralphbean/ansi2html
tiv: https://github.com/stefanhaustein/TerminalImageViewer
bat: https://github.com/sharkdp/bat
GNU source-highlite: https://www.gnu.org/software/src-highlite/
bash-drawille: https://github.com/mydzor/bash-drawille
additional info: https://oioiiooixiii.blogspot.com/2018/03/bash-seven-applications-designed-to.html
image source: (CC BY 2.0) https://www.flickr.com/photos/usdagov/20190061980
image source: http://www.thejournal.ie/readme/vincent-brown-eighth-amendment-yes-vote-4026621-May2018/

Bash: Create a cacophony of voices with 'Mimic' text-to-speech



A somewhat grotesque and macabre presentation of 'Mimic's text-to-speech functionality. The concept arising after recently trying out 'Mimic's features and capabilities. As a short review; I believe 'Mimic's main strengths lie in its speed and ease of execution on the command line, similar to that of 'espeak'. Other more featured text-to-speech solutions can be slow and cumbersome to initiate.

N.B. In the video, there are an unfortunate number of artifacts in the audio. These only manifest in PulseAudio stream recording and are not present while monitoring the audio in real-time.

#!/bin/bash
# (GNU bash, version 4.4.19(1)-release)
#
# Create a cacophony of 'Mimic' text-to-speech voices, using words found in the
# system's 'words' file. Note: The concept can be applied to any text-to-speech
# software and, as such, a rudimentary function using 'espeak' is included.
# (Mimic info: https://mycroft.ai/documentation/mimic/)
# - Optional parameters: '$1' number of words - '$2' Number of voices
#
# Version: 2018.08.11.15.54.15
# Source: https://oioiiooixiii.blogspot.com

function randWords() # RETURNS PUNCTUATED LIST OF WORDS FROM SYSTEM DICTIONARY
{
   shuf </usr/share/dict/words \
   | head -"$1" \
   | awk 1 ORS='. '
}

function randNum() # RETURNS RANDOM NUMBER BETWEEN '$1' and '$2'
{
   shuf -i "$1"-"$2" -n 1
}

function randVoice() # RETURNS NAME OF RANDOM MIMIC VOICE
{
   local voices=("ap" "slt" "kal" "awb" "kal16" "rms")
   printf "${voices[$(randNum 0 ${#voices[@]})]}"
}

function mimicSpeak() # INVOKES 'MIMIC' APPLICATION
{
   mimic \
      -voice "$(randVoice)" \
      --setf int_f0_target_mean="$(randNum 20 180)" \
      --setf duration_stretch="$(randNum 1 12)" \
      <<<"$1"
}

function espeakAlt() # INVOKES 'ESPEAK' ALTERNATIVE
{
   espeak \
      -p "$(randNum 1 200)" \
      -s "$(randNum 1 100)" \
      "$1"
}

function main()
{
   clear

   for (( i=0;i<"${2:-5}";i++  ))
   {
      local sentence="$(randWords "${1:-5}")"
      echo "$sentence"
      mimicSpeak "$sentence" &
      #espeakAlt "$sentence" &
   }
}

main "$@"
exit

#### NOTES: One line concept

# shuf </usr/share/dict/british-english \
# | head -5 \
# | sed ':a;N;$!ba;s/\n/. /g' \
# | tee > \
#   (
#       mimic \
#          -voice slt \
#          --setf int_f0_target_mean=50 \
#          --setf duration_stretch=16 \
#   )
download: mimic-cacophony.sh

Brutal Doom: Stablised




Zandronum window stablised using default 'VidStab' stablisation settings via FFmpeg.

related: https://oioiiooixiii.blogspot.com/2016/09/ffmpeg-video-stabilisation-using.html
more info: https://doomwiki.org/wiki/Project_Brutality