commit 541f20eb6ecbc6617286bfc0b9175d02f85ca83e Author: borja Date: Mon Feb 10 10:10:58 2025 +0100 Initial commit with two utilities: reducepdf and whisper diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86c6a01 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +markitdown diff --git a/README.md b/README.md new file mode 100644 index 0000000..0735e88 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# My ./local/bin collection of scripts for my convenience + +Currently done from my work computer, I have the following utilities: + +- `reducepdf.sh`: Reduce a PDF file size by reducing the ppi of the images. +- `whisper.sh`: Transcribe audio and video files directly in the directory they're on. diff --git a/reducepdf.sh b/reducepdf.sh new file mode 100755 index 0000000..b279aa7 --- /dev/null +++ b/reducepdf.sh @@ -0,0 +1,83 @@ +#!/bin/bash + +# Function to display usage information and exit +usage() { + echo "Usage: $0 input.pdf output.pdf [-r resolution] [-h]" + echo "" + echo "Options:" + echo "-r Set the image resolution (default is 150ppi)" + echo "-h Display this help message" + exit 1 +} + +# Default settings +RESOLUTION=150 + +# Parse command-line options +while getopts ":r:h" opt; do + case ${opt} in + r) + RESOLUTION=$OPTARG + ;; + h) + usage + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + :) + echo "Option -$OPTARG requires an argument." >&2 + exit 1 + ;; + esac +done + +shift $((OPTIND - 1)) + +# Check if the correct number of arguments are provided after parsing options +if [ "$#" -ne 2 ]; then + usage +fi + +INPUT_FILE="$1" +OUTPUT_FILE="$2" + +# Check if input file exists +if [ ! -f "$INPUT_FILE" ]; then + echo "Input file '$INPUT_FILE' does not exist." + exit 1 +fi + +# Extract directory and base name from output file path +OUTPUT_DIR=$(dirname "$OUTPUT_FILE") +OUTPUT_BASENAME=$(basename "$OUTPUT_FILE") + +# Create the output directory if it doesn't already exist +mkdir -p "$OUTPUT_DIR" + +# Run Ghostscript command with specified resolution +gs \ + -sDEVICE=pdfwrite \ + -dCompatibilityLevel=1.7 \ + -dPDFSETTINGS=/prepress \ + -dDownsampleMonoImages=false \ + -dDownsampleColorImages=true \ + -dColorImageResolution=$RESOLUTION \ + -dGrayImageResolution=$RESOLUTION \ + -dMonoImageResolution=$RESOLUTION \ + -dPreserveOPIRequests=false \ + -dSubsetFonts=true \ + -dEmbedAllFonts=true \ + -sProcessColorModel=DeviceRGB \ + -dQUIET -dBATCH -dNOPAUSE \ + -sOutputFile="$OUTPUT_FILE" "$INPUT_FILE" + +# Check if Ghostscript command was successful +if [ $? -ne 0 ]; then + echo "Error: Ghostscript failed to process the file '$INPUT_FILE'." + exit 1 +fi + +echo "Successfully converted '$INPUT_FILE' to '$OUTPUT_BASENAME'" + diff --git a/whisper.sh b/whisper.sh new file mode 100755 index 0000000..d083aab --- /dev/null +++ b/whisper.sh @@ -0,0 +1,130 @@ +#!/bin/bash +# Script that uses `whispercpp` to tranascribe audio and video files automatically and outputs the results in the same directory + +# Configuración +REPO_DIR=~/code/whisper.cpp +WHISPER_CLI="$REPO_DIR/build/bin/whisper-cli" +TEMP_DIR=$(mktemp -d) +LANGUAGE="en" +OUTPUT_FORMAT="txt" + +# Rutas de los modelos +MODEL_LARGE="/Users/borjarobert/code/whisper.cpp/models/ggml-large-v3-turbo.bin" +MODEL_MEDIUM="/Users/borjarobert/code/whisper.cpp/models/ggml-medium.bin" +MODEL_SMALL="/Users/borjarobert/code/whisper.cpp/models/ggml-base.bin" +MODEL_PATH="$MODEL_LARGE" # Valor por defecto + +# Función para mostrar uso +usage() { + echo "Uso: whisper [-u] [-t archivo] [-m modelo] [-l idioma] [-f formato]" + echo "Opciones:" + echo " -u Actualiza y recompila whispercpp" + echo " -t archivo Transcribe el archivo de video" + echo " -m modelo Especifica el modelo (large, medium, small)" + echo " -l idioma Especifica el idioma (por defecto: en)" + echo " -f formato Especifica el formato de salida (txt, srt, json, vtt, lrc, csv)" + exit 1 +} + +# Manejo de argumentos +while getopts ":ut:m:l:f:" opt; do + case $opt in + u) + echo "Actualizando whispercpp..." + cd "$REPO_DIR" || exit + git pull + make + echo "Actualización completa." + exit 0 + ;; + t) + FILE="$OPTARG" + ;; + m) + case $OPTARG in + large) + MODEL_PATH="$MODEL_LARGE" + ;; + medium) + MODEL_PATH="$MODEL_MEDIUM" + ;; + small) + MODEL_PATH="$MODEL_SMALL" + ;; + *) + echo "Modelo no válido: $OPTARG. Usando el modelo por defecto (large)." + ;; + esac + ;; + l) + LANGUAGE="$OPTARG" + ;; + f) + OUTPUT_FORMAT="$OPTARG" + ;; + \?) + echo "Opción inválida: -$OPTARG" >&2 + usage + ;; + :) + echo "La opción -$OPTARG requiere un argumento." >&2 + usage + ;; + esac +done + +# Verificar si se proporcionó un archivo para transcribir +if [ -z "$FILE" ]; then + usage +fi + +# Verificar si whisper-cli está disponible +if ! command -v "$WHISPER_CLI" &>/dev/null; then + echo "Error: whisper-cli no se encuentra en $WHISPER_CLI" + exit 1 +fi + +# Convertir archivo a WAV +WAV_FILE="$TEMP_DIR/$(basename "$FILE" .mp4).wav" +ffmpeg -i "$FILE" -acodec pcm_s16le -ac 1 -ar 16000 "$WAV_FILE" -y || { + echo "Error al convertir a WAV" + rm -rf "$TEMP_DIR" + exit 1 +} + +# Preparar nombres de salida +OUTPUT_BASE="$(basename "$FILE" .mp4)_${LANGUAGE}" +OUTPUT_DIR="$(pwd)" # Directorio actual +OUTPUT_FILE="$OUTPUT_DIR/$OUTPUT_BASE" + +# Transcribir +case "$OUTPUT_FORMAT" in +txt) + $WHISPER_CLI -m "$MODEL_PATH" -l "$LANGUAGE" -otxt -of "$OUTPUT_FILE" "$WAV_FILE" | tee "$OUTPUT_FILE"_timestamped.txt + ;; +srt) + $WHISPER_CLI -m "$MODEL_PATH" -l "$LANGUAGE" -osrt -of "$OUTPUT_FILE" "$WAV_FILE" | tee "$OUTPUT_FILE"_timestamped.txt + ;; +json) + $WHISPER_CLI -m "$MODEL_PATH" -l "$LANGUAGE" -oj -of "$OUTPUT_FILE" "$WAV_FILE" | tee "$OUTPUT_FILE"_timestamped.txt + ;; +vtt) + $WHISPER_CLI -m "$MODEL_PATH" -l "$LANGUAGE" -ovtt -of "$OUTPUT_FILE" "$WAV_FILE" | tee "$OUTPUT_FILE"_timestamped.txt + ;; +lrc) + $WHISPER_CLI -m "$MODEL_PATH" -l "$LANGUAGE" -olrc -of "$OUTPUT_FILE" "$WAV_FILE" | tee "$OUTPUT_FILE"_timestamped.txt + ;; +csv) + $WHISPER_CLI -m "$MODEL_PATH" -l "$LANGUAGE" -ocsv -of "$OUTPUT_FILE" "$WAV_FILE" | tee "$OUTPUT_FILE"_timestamped.txt + ;; +*) + echo "Formato de salida no soportado: $OUTPUT_FORMAT" + rm -rf "$TEMP_DIR" + exit 1 + ;; +esac + +# Limpiar archivos temporales +rm -rf "$TEMP_DIR" + +echo "Transcripción completada. Archivos generados: ${OUTPUT_FILE}_timestamped.txt y ${OUTPUT_FILE}.${OUTPUT_FORMAT}."