#!/usr/bin/env bash

set -o errexit
set -o pipefail
set -o nounset

usage() {
cat << EOF
Uso:
  $(basename "${0}") -v VIDEO (-t TIEMPO | -n FRAME) [opciones]

Opciones:
  -v VIDEO       Ruta del vídeo
  -t TIEMPO      Instante (ej: 00:01:23.450)
  -n FRAME       Número de frame
  -o DIR         Directorio de salida (por defecto: mismo del vídeo)
  -f FORMATO     png | jpg (por defecto: png)
  -h             Mostrar ayuda

Ejemplos:

Extraer frame por tiempo
  $0 -v video.mp4 -t 00:01:10.250

Extraer frame por número
  $0 -v video.mp4 -n 1200

Guardar en otro directorio
  $0 -v video.mp4 -t 00:00:10 -o frames/

EOF
exit 1
}

VIDEO=""
TIME=""
FRAME=""
OUTDIR=""
FORMAT="png"

while getopts ":v:t:n:o:f:h" opt; do
    case "$opt" in
        v) VIDEO="$OPTARG" ;;
        t) TIME="$OPTARG" ;;
        n) FRAME="$OPTARG" ;;
        o) OUTDIR="$OPTARG" ;;
        f) FORMAT="$OPTARG" ;;
        h) usage ;;
        *) usage ;;
    esac
done

if [[ -z "$VIDEO" ]]; then
    echo "Error: debes indicar un vídeo."
    usage
fi

if [[ -z "$TIME" && -z "$FRAME" ]]; then
    echo "Error: debes indicar tiempo (-t) o número de frame (-n)."
    usage
fi

if [[ -n "$TIME" && -n "$FRAME" ]]; then
    echo "Error: usa solo -t o -n."
    usage
fi

if ! command -v ffmpeg >/dev/null 2>&1; then
    echo "Error: ffmpeg no está instalado."
    exit 1
fi

if [[ ! -f "$VIDEO" ]]; then
    echo "Error: el vídeo no existe."
    exit 1
fi

DIR=$(dirname -- "$VIDEO")
FILE=$(basename -- "$VIDEO")
BASE="${FILE%.*}"

if [[ -z "$OUTDIR" ]]; then
    OUTDIR="$DIR"
fi

mkdir -p "$OUTDIR"

# calcular siguiente número
next_num=$(
ls "$OUTDIR/${BASE}-frame-"*.$FORMAT 2>/dev/null |
sed -E "s/.*-frame-([0-9]+)\.$FORMAT/\1/" |
sort -n |
tail -n1
)

if [[ -z "${next_num:-}" ]]; then
    next_num=1
else
    ((next_num++))
fi

NUM=$(printf "%03d" "$next_num")
OUT="$OUTDIR/${BASE}-frame-$NUM.$FORMAT"

echo
echo "Video      : $VIDEO"
[[ -n "$TIME" ]] && echo "Tiempo     : $TIME"
[[ -n "$FRAME" ]] && echo "Frame      : $FRAME"
echo "Salida     : $OUT"
echo

if [[ -n "$TIME" ]]; then

    ffmpeg -loglevel error \
        -ss "$TIME" \
        -i "$VIDEO" \
        -frames:v 1 \
        "$OUT"

else

    FPS=$(ffprobe -v 0 -select_streams v:0 \
        -show_entries stream=r_frame_rate \
        -of default=noprint_wrappers=1:nokey=1 "$VIDEO")

    FPS=$(awk -F/ '{printf "%.6f", $1/$2}' <<< "$FPS")

    TIME=$(awk -v f="$FRAME" -v fps="$FPS" 'BEGIN {printf "%.6f", f/fps}')

    ffmpeg -loglevel error \
        -ss "$TIME" \
        -i "$VIDEO" \
        -frames:v 1 \
        "$OUT"

fi

echo "✔ Frame extraído correctamente."
echo