MENU

Add movie preview to vifm

vifm
目次

Need movie preview

Finder on MacOS is not so useful, but vifm is faster & easy to use.
So I want to set it up as 2nd(1st?) image/movie viewer too.
Add movie preview function to vifm, with ffmpeg & zsh script.
(Image previewing function will be released in later article.)

Newer version can be downloaded here

preview.vifm : image/video preview
https://github.com/riodelphino/preview.vifm

Below codes are old and buggy.

Ensured to work on

  • kitty
  • tmux on kitty

Features

  • Generate & save preview images(png) using ffmpeg
  • Async generation in background for all files in the directory. (Faster !!)
  • Frame number for cutting out
  • Logging if needed

Code

Preparing

# Prepairing
mkdir ~/.config/vifm/scripts
cd ~/.config/vifm/scripts
touch preview_movie.sh
chmod +x preview_movie.sh
Zsh

preview_movie.sh

#!/bin/bash

# USAGE:
#    ./preview_movie.sh [file_name] [process_all]
#
# ARGS:
#    file_name     : movie filename
#    process_all   : 0: Generate preview for the single file
#                    1: Generate previews for all files in the dir

# --------------------------------------------------------------------------------
# Consts
# --------------------------------------------------------------------------------
CACHE_DIR="$HOME/.cache/vifm/preview/movie"
FRAME=1000       # frame num for cut, from the movie's start
SCALE="640:360" # width(px):height(px) : Just size without '--scale-up' is faster
PREV_DIR_FILE="$HOME/.cache/vifm/preview/movie/.prev_dir"
PATTERN="*.avi *.mp4 *.wmv *.dat *.3gp *.ogv *.mkv *.mpg *.mpeg *.vob fl[icv] *.m2v *.mov *.webm *.ts *.mts *.m4v r[am] *.qt *.divx as[fx]"
LOG_FILE="$HOME/.cache/vifm/preview/movie/log"
LOG=0 # 0: No logging | 1: Logging (cause timeloss)

# --------------------------------------------------------------------------------
# Variables
# --------------------------------------------------------------------------------
prev_dir=""
cur_dir=""

# --------------------------------------------------------------------------------
# Functions
# --------------------------------------------------------------------------------

# Loging
function Log() {
   if [[ $LOG == 1 ]]; then
      echo "$1" >>"$LOG_FILE"
   fi
}

# Generate preview & return the path & record current dir
function GeneratePreview() {
   # Get preview path
   fname="${1%.*}"                 # filename without extension
   bname=$(basename "$fname")      # remove directories
   preview="$CACHE_DIR/$bname.png" # preview path

   # Generate preview
   if [ ! -f "$preview" ]; then
      ffmpeg -y -i "$1" \
         -vf "select='eq(n,$FRAME)',scale=$SCALE" \
         -frames:v 1 \
         "$preview" >/dev/null 2>&1 # Move & here to background the ffmpeg process
   fi
   echo $preview
}

# Record current directory
function RecordCurDir() {
   echo $cur_dir >"$PREV_DIR_FILE"
}

# Generate previews for all files in dir
function GeneratePreviewAll() {
   # List files in the directory and loop through each pattern
   for pat in "${PATTERN[@]}"; do
      # For each pattern, find matching files
      for file in "$cur_dir"/$pat; do
         # Only proceed if $file is a regular file
         if [[ -f "$file" ]]; then
            Log "file        : $file"
            GeneratePreview "$file"
         fi
      done
   done
   wait
}

# --------------------------------------------------------------------------------
# Main script
# --------------------------------------------------------------------------------

# Get directories
cur_dir=$(dirname "$(realpath "$1")")
[ ! -f "$PREV_DIR_FILE" ] && prev_dir="" || prev_dir=$(cat "$PREV_DIR_FILE")

# Logging
Log "process_all : $2"
Log "prev_dir    : $prev_dir"
Log "cur_dir     : $cur_dir"
Log "file        : $1"

PROCESS_ALL_FILES=$2

# Create preview directory
mkdir -p "$CACHE_DIR"

if [[ $PROCESS_ALL_FILES == 1 ]]; then
   # GeneratePreviewAll()' (in background)
   Log "function    : GeneratePreviewAll()"
   if [[ "$prev_dir" != "$cur_dir" ]]; then # Check if the directory has changed
      GeneratePreviewAll "$cur_dir"
   fi
else
   # Generate preview for the single file
   Log "function    : GeneratePreview()"
   GeneratePreview "$1"
fi

Log "function    : RecordCurDir()"
RecordCurDir "$1"
Zsh

vifmrc

" ~/.config/vifm/vifmrc

fileviewer {*.avi,*.mp4,*.wmv,*.dat,*.3gp,*.ogv,*.mkv,*.mpg,*.mpeg,*.vob,*.fl[icv],*.m2v,*.mov,*.webm,*.ts,*.mts,*.m4v,*.r[am],*.qt,*.divx,*.as[fx]},
   \ sh -c "$HOME/.config/vifm/scripts/preview_movie.sh '%c' 1 &" ; kitten icat --transfer-mode=file --silent --scale-up --place=%pwx%ph@%pxx%py "$($HOME/.config/vifm/scripts/preview_movie.sh '%c' 0 &)" >/dev/tty </dev/tty %N
   \ %pc
   \ kitten icat --clear --silent >/dev/tty </dev/tty %N &
Plaintext

If you use other terminals, modify kitten icat to your own commands like Sixel or iTerm2 Image Protocol , e.t.c.
But I’m not sure they work or not.

Explanation

# Cache directory
CACHE_DIR="$HOME/.cache/vifm/preview/movie"

# Frame number from the start, to cut out preview png
FRAME=1000
# The bigger it is, the longer it takes time.

# Preview scale, width(px):height(px)
SCALE="640:360"
# Exact size without scaling up is much faster.
#   - Fix your col or row split size
#   - Measure the max height & width in pixel
#   - Set the values here
#   - Remove '--scale-up' from 'kitten icat' command options

# The file path to save previous directory
PREV_DIR_FILE="$HOME/.cache/vifm/preview/movie/.prev_dir"

# Movie patterns (split by space)
PATTERN="*.avi *.mp4 *.wmv *.dat *.3gp *.ogv *.mkv *.mpg *.mpeg *.vob fl[icv] *.m2v *.mov *.webm *.ts *.mts *.m4v r[am] *.qt *.divx as[fx]"

# Log file path
LOG_FILE="$HOME/.cache/vifm/preview/movie/log"

# Logging or not
LOG=0 # 0: No logging | 1: Logging (cause timeloss)
Zsh
fileviewer {*.avi,*.mp4,*.wmv,*.dat,*.3gp,*.ogv,*.mkv,*.mpg,*.mpeg,*.vob,*.fl[icv],*.m2v,*.mov,*.webm,*.ts,*.mts,*.m4v,*.r[am],*.qt,*.divx,*.as[fx]},
Plaintext

This must match the PATTERN

\ sh -c "$HOME/.config/vifm/scripts/preview_movie.sh '%c' 1 &" ;
Plaintext

Executing GeneratePreviewAll()for the directory of %c.
%cFile path
1 This 2nd arg select generating 0:The single file or 1:All files in the direcotry.
& async in background

kitten icat --transfer-mode=file --silent --scale-up --place=%pwx%ph@%pxx%py "$($HOME/.config/vifm/scripts/preview_movie.sh '%c' 0 &)" >/dev/tty </dev/tty %N
Plaintext

Excuting GeneratePreview() for the single file %c, then show it by kitten icat.
%c File path
0 Same above.
& Async (Isn’t it useful?)
kitten icat and options should be relpaced to your own command.

\ %pc
Plaintext

It’s just a delimiter for the first displaying command and last cleaning command.

\ kitten icat --clear --silent >/dev/tty </dev/tty %N &
Plaintext

Cleaing command for the existing images on terminal.

To-do

  • Preview filename is same with the original.
  • So, in some cases, the same filenames in different directories will cause conflict & no generating newer preview image.
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメント一覧 (1件)

  • […] Finder on MacOS is not so useful, but vifm is faster & easy to use.So I want to set it up as 2nd(1st?) image/video viewer too.Add image/video previewing function to vifm, with ffmpeg & bash script.(More simple video previewing script is here.) […]

コメントする

目次