kamiyaa / joshuto

ranger-like terminal file manager written in Rust
https://crates.io/crates/joshuto
GNU Lesser General Public License v3.0
3.47k stars 154 forks source link

Video preview image #242

Open maximyurevich opened 1 year ago

maximyurevich commented 1 year ago

It will be cool to have video preview in joshuto, like lf file manager with https://github.com/NikitaIvanovV/ctpv

Sonico98 commented 1 year ago

It can be done by modifying the already existing image preview scripts and using ffmpegthumbnailer. With kitty: on_preview_shown.sh

#!/usr/bin/env bash

FILE_PATH="$1"          # Full path of the previewed file
PREVIEW_X_COORD="$2"        # x coordinate of upper left cell of preview area
# PREVIEW_Y_COORD="$3"
PREVIEW_WIDTH="$4"      # Width of the preview pane (number of fitting characters)
PREVIEW_HEIGHT="$5"     # Height of the preview pane (number of fitting characters)
let PREVIEW_Y_COORD="$PREVIEW_HEIGHT"/5     # y coordinate of upper left cell of preview area

mkdir -p "$HOME/.cache/joshuto"
TMP_FILE="$HOME/.cache/joshuto/thumbcache.png"

mimetype=$(file --mime-type -Lb "$FILE_PATH")

function kclear {
    kitty +kitten icat \
        --transfer-mode=file \
        --clear 2>/dev/null
}

function image {
    kclear
    kitty +kitten icat \
        --transfer-mode=file \
        --place "${PREVIEW_WIDTH}x${PREVIEW_HEIGHT}@${PREVIEW_X_COORD}x${PREVIEW_Y_COORD}" \
        "$1" 2>/dev/null
}

case "$mimetype" in
    image/*)
        thumbnail="$(allmytoes -sx "$FILE_PATH" 2>/dev/null)"
        if [ "$thumbnail" ]; then
            image "${thumbnail}"
        else
            kclear
        fi
        ;;
    video/*)
        kclear
        ffmpegthumbnailer -i "$FILE_PATH" -f -m -c png -s 0 -o - 2>/dev/null | \
            kitty +kitten icat --transfer-mode=stream --place \
            "${PREVIEW_WIDTH}x${PREVIEW_HEIGHT}@${PREVIEW_X_COORD}x${PREVIEW_Y_COORD}"
        ;;
    *)
        kclear
        ;;
esac

For preview_file.sh, look for the handle_mime function (line 175 as of the time of writing) and add the following after the image/ case. You would have to add it at line 231 as of the time of writing. I've included the image/ case here for context, but you should just care about the video part. Don't copy the triple dots either.

...

        image/*)
            ## Preview as text conversion
            # img2txt --gamma=0.6 --width="${PREVIEW_WIDTH}" -- "${FILE_PATH}" && exit 4
            exiftool "${FILE_PATH}" && exit 5
            exit 1;;

        video/*)
        dimension="Size: $(exiftool -ImageSize "$path" | awk '{print $4}')"
        echo "$dimension"
            meta_file="$(get_preview_meta_file $path)"
        y_offset=4
            echo "y-offset $y_offset" > "$meta_file"
            exit 4
        ;;

...

Result image

It would be great, however, if videos could ignore the max_preview_size option in joshuto.toml

maximyurevich commented 1 year ago

It can be done by modifying the already existing image preview scripts and using ffmpegthumbnailer. With kitty: on_preview_shown.sh

#!/usr/bin/env bash

FILE_PATH="$1"            # Full path of the previewed file
PREVIEW_X_COORD="$2"      # x coordinate of upper left cell of preview area
# PREVIEW_Y_COORD="$3"
PREVIEW_WIDTH="$4"        # Width of the preview pane (number of fitting characters)
PREVIEW_HEIGHT="$5"       # Height of the preview pane (number of fitting characters)
let PREVIEW_Y_COORD="$PREVIEW_HEIGHT"/5       # y coordinate of upper left cell of preview area

mkdir -p "$HOME/.cache/joshuto"
TMP_FILE="$HOME/.cache/joshuto/thumbcache.png"

mimetype=$(file --mime-type -Lb "$FILE_PATH")

function kclear {
  kitty +kitten icat \
      --transfer-mode=file \
      --clear 2>/dev/null
}

function image {
  kclear
  kitty +kitten icat \
      --transfer-mode=file \
      --place "${PREVIEW_WIDTH}x${PREVIEW_HEIGHT}@${PREVIEW_X_COORD}x${PREVIEW_Y_COORD}" \
      "$1" 2>/dev/null
}

case "$mimetype" in
  image/*)
      thumbnail="$(allmytoes -sx "$FILE_PATH" 2>/dev/null)"
      if [ "$thumbnail" ]; then
          image "${thumbnail}"
      else
          kclear
      fi
      ;;
  video/*)
      ffmpegthumbnailer -i "$FILE_PATH" -f -m -c png -s 0 -o - | \
          kitty +kitten icat --transfer-mode=stream --place \
          "${PREVIEW_WIDTH}x${PREVIEW_HEIGHT}@${PREVIEW_X_COORD}x${PREVIEW_Y_COORD}"
      ;;
  *)
      kclear
      ;;
esac

For preview_file.sh, look for the handle_mime function (line 175 as of the time of writing) and add the following after the image/ case. You would have to add it at line 231 as of the time of writing. I've included the image/ case here for context, but you should just care about the video part. Don't copy the triple dots either.

...

        image/*)
            ## Preview as text conversion
            # img2txt --gamma=0.6 --width="${PREVIEW_WIDTH}" -- "${FILE_PATH}" && exit 4
            exiftool "${FILE_PATH}" && exit 5
            exit 1;;

        video/*)
      dimension="Size: $(exiftool -ImageSize "$path" | awk '{print $4}')"
      echo "$dimension"
            meta_file="$(get_preview_meta_file $path)"
      y_offset=4
            echo "y-offset $y_offset" > "$meta_file"
            exit 4
      ;;

...

Result image

It would be great, however, if videos could ignore the max_preview_size option in joshuto.toml

I use alacritty, what about ueberzug?

Sonico98 commented 1 year ago

I use alacritty, what about ueberzug?

Do the same steps I did above for preview_file.sh, and modify ueberzug's on_preview_shown script in the following way:

#!/usr/bin/env bash

test -z "$joshuto_wrap_id" && exit 1;

path="$1"       # Full path of the previewed file
x="$2"          # x coordinate of upper left cell of preview area
# y="$3"          # y coordinate of upper left cell of preview area
width="$4"      # Width of the preview pane (number of fitting characters)
height="$5"     # Height of the preview pane (number of fitting characters)
let y="$height"/5

# Find out mimetype and extension
mimetype=$(file --mime-type -Lb "$path")
extension=$(/bin/echo "${path##*.}" | awk '{print tolower($0)}')

case "$mimetype" in
    image/png | image/jpeg)
        show_image "$path" $x $y $width $height
        ;;
    video/*)
        ffmpegthumbnailer -i "$path" -f -m -c png -s 0 -o /tmp/vid.png 2>/dev/null
        show_image /tmp/vid.png $x $y $width $height
        sleep 5 && rm -f /tmp/vid.png
        ;;
    *)
        remove_image
esac

Someone better than me could figure out how to avoid writing the thumbnail to /tmp/vid.png, but for now, this works. image

Sonico98 commented 1 year ago

I guess this issue can be closed @maximyurevich?

maximyurevich commented 1 year ago

I guess this issue can be closed @maximyurevich?

I don't use joshuto anymore, the ranger git version is working fine, for me your examples don't work

kamiyaa commented 1 year ago

I will keep this open in case future users run into similar problems :+1:

AngelontheRoad commented 1 year ago

I use alacritty, what about ueberzug?

Do the same steps I did above for preview_file.sh, and modify ueberzug's on_preview_shown script in the following way:

#!/usr/bin/env bash

test -z "$joshuto_wrap_id" && exit 1;

path="$1"       # Full path of the previewed file
x="$2"          # x coordinate of upper left cell of preview area
# y="$3"          # y coordinate of upper left cell of preview area
width="$4"      # Width of the preview pane (number of fitting characters)
height="$5"     # Height of the preview pane (number of fitting characters)
let y="$height"/5

# Find out mimetype and extension
mimetype=$(file --mime-type -Lb "$path")
extension=$(/bin/echo "${path##*.}" | awk '{print tolower($0)}')

case "$mimetype" in
    image/png | image/jpeg)
        show_image "$path" $x $y $width $height
        ;;
    video/*)
        ffmpegthumbnailer -i "$path" -f -m -c png -s 0 -o /tmp/vid.png 2>/dev/null
        show_image /tmp/vid.png $x $y $width $height
        sleep 5 && rm -f /tmp/vid.png
        ;;
    *)
        remove_image
esac

Someone better than me could figure out how to avoid writing the thumbnail to /tmp/vid.png, but for now, this works. image j Video thumbnail won't change in my case. Seems that each terminal instance has a cache for the first video and the cache is not deleted when preview next video.

EvanCarroll commented 1 year ago

What is

  thumbnail="$(allmytoes -sx "$FILE_PATH" 2>/dev/null)"

Where are you getting this utility?

DLFW commented 1 year ago

What is

  thumbnail="$(allmytoes -sx "$FILE_PATH" 2>/dev/null)"

Where are you getting this utility?

Hi, allmytoes lives here on GitLab. I'm the author but unfortunately, I haven't found time in the last months to work on it. But I will pick up development again end of Sep. or so. BTW, providing thumbs for non-image files (for example videos) is in the queue.