Releases: hitmux/hitvid
hitvid v1.2.0
Die Go-Implementierung ist der Shell-Version in fast jeder Hinsicht architektonisch überlegen. Die primäre Empfehlung ist, die Go-Version als primäre Codebasis zu übernehmen und weiterzuentwickeln, während das Shell-Skript als Prototyp betrachtet wird. Die Go-Version bietet eine solide Grundlage für hohe Leistung, Stabilität und zukünftige Erweiterbarkeit. Die folgenden Abschnitte beschreiben die Stärken und Schwächen beider Versionen und schlagen konkrete Verbesserungen für die Go-Implementierung vor.
1. Vergleichende Analyse
1.1 Architektur und Design
-
Go-Implementierung (
hitvid_Go):- Stärken:
- Struktur: Nutzt eine kompilierte, statisch typisierte Sprache, die für mehr Leistung und Typsicherheit sorgt.
- Gleichzeitigkeit: Verwendet idiomatische Go-Konstrukte wie Goroutinen, Kanäle (
channels), Mutexes und Bedingungsvariablen (sync.Cond). Dies ermöglicht eine saubere und effiziente Parallelverarbeitung von Frame-Rendering und Benutzereingaben. - Zustandsverwaltung: Der Zustand der Anwendung (z. B. Pause, Wiedergabegeschwindigkeit) wird zentral in Variablen verwaltet und durch einen Mutex geschützt, was die Komplexität reduziert und Race Conditions verhindert.
- IPC (Inter-Process Communication): Gerenderte Frames werden direkt im Arbeitsspeicher (
renderedFrames [][]byte) gehalten, was den extrem langsamen Festplatten-I/O des Shell-Skripts vermeidet.
- Stärken:
-
Shell-Implementierung (
hitvid_Shell):- Schwächen:
- Komplexität: Mit über 600 Zeilen ist das Skript extrem komplex und schwer zu warten. Die Logik für die Prozessverwaltung, Fehlerbehandlung und Gleichzeitigkeit ist verschachtelt und unübersichtlich.
- Gleichzeitigkeit: Die Parallelverarbeitung wird durch das manuelle Starten und Überwachen von Hintergrundprozessen (
ffmpeg,chafa) realisiert. Die Synchronisation erfolgt durchsleep-Befehle und das ständige Überprüfen von Dateiexistenzen (while [ ! -f ... ]), was ineffizient und fehleranfällig ist. - IPC: Der gesamte Prozess basiert auf dem Schreiben und Lesen von Tausenden von einzelnen JPEG- und Textdateien auf der Festplatte. Dies ist der größte Leistungsengpass. Auch die Verwendung von
/dev/shm(RAM-Disk) löst das grundlegende Problem des dateibasierten IPC nicht vollständig.
- Schwächen:
1.2 Leistung
-
Go-Implementierung:
- Rendering-Pipeline: Die Verwendung eines Worker-Pools aus Goroutinen zum Rendern von Frames ist hocheffizient.
- Overhead: Da es sich um ein kompiliertes Binary handelt, gibt es praktisch keinen Interpreter-Overhead während der Wiedergabe. Berechnungen erfolgen nativ und schnell.
- Engpass: Der Hauptleistungsengpass ist die Geschwindigkeit von
ffmpegundchafaselbst, nicht die Orchestrierung durch das Go-Programm.
-
Shell-Implementierung:
- Rendering-Pipeline: Der
preload-Modus mitxargs -Pist für die Parallelisierung effektiv. Derstream-Modus mit seinem manuell verwalteten Daemon ist jedoch umständlich und langsam. - Overhead: Jeder Aufruf von
awk,bc,date,tputundgrepin der Wiedergabeschleife erzeugt einen neuen Prozess (fork/exec), was zu einem massiven Leistungsabfall führt. - Engpass: Der Festplatten-I/O für die Frame-Dateien ist der mit Abstand größte Engpass und begrenzt die maximal erreichbare Framerate erheblich.
- Rendering-Pipeline: Der
1.3 Robustheit und Fehlerbehandlung
-
Go-Implementierung:
- Graceful Shutdown:
context.Contextwird korrekt verwendet, um alle Goroutinen bei Benutzeraktionen (z. B. Beenden, nächstes Video) sauber zu beenden. - Fehlerbehandlung: Fehler werden explizit behandelt (
if err != nil), was den Code vorhersehbar und robust macht. - Ressourcenmanagement:
defer-Anweisungen stellen sicher, dass Ressourcen wie temporäre Verzeichnisse und der Terminalzustand zuverlässig bereinigt werden.
- Graceful Shutdown:
-
Shell-Implementierung:
- Graceful Shutdown: Die
cleanup-Funktion, die übertrapaufgerufen wird, ist eine gute Vorgehensweise für Shell-Skripte, aber die korrekte Beendigung aller Kind- und Enkelprozesse ist komplex und nicht immer garantiert. - Fehlerbehandlung: Die Fehlerbehandlung ist verstreut und verlässt sich auf die Überprüfung von Exit-Codes (
$?), was oft zu unbemerkten Fehlern führen kann.
- Graceful Shutdown: Die
2. Detaillierter Verbesserungsplan für die Go-Implementierung
Die Go-Version ist eine ausgezeichnete Grundlage. Die folgenden Verbesserungen zielen darauf ab, sie noch leistungsfähiger, ressourcenschonender und funktionsreicher zu machen.
2.1 Architektur & Speicherverwaltung
- Problem: Die aktuelle Implementierung speichert alle gerenderten Frames im RAM (
renderedFrames [][]byte). Bei langen oder hochauflösenden Videos kann dies zu einem extrem hohen Speicherverbrauch führen. - Empfehlung: Implementierung eines begrenzten Frame-Caches (Ringpuffer).
- Aktion: Ersetzen Sie das unbegrenzte Slice
renderedFramesdurch eine Datenstruktur mit fester Größe (z. B. ein Puffer für 300 Frames). - Logik:
- Der Rendering-Worker schreibt einen neuen Frame in den Puffer.
- Der Wiedergabe-Loop liest Frames aus dem Puffer.
- Wenn der Puffer voll ist, pausiert der Dispatcher das Einreihen neuer Render-Jobs, bis die Wiedergabe Platz schafft.
- Bei einem Suchvorgang (seek) wird der Puffer geleert und mit Frames um den neuen Wiedergabepunkt herum neu befüllt.
- Vorteil: Drastische Reduzierung des Speicherverbrauchs, wodurch die Anwendung auch bei langen Videos stabil läuft.
- Aktion: Ersetzen Sie das unbegrenzte Slice
2.2 Leistung und Gleichzeitigkeit
- Problem: Der globale
stateMutexwird von mehreren Goroutinen (Wiedergabeschleife, Eingabehandler, Rendering-Worker) gleichzeitig verwendet, was zu potenziellen Latenzen führen kann. - Empfehlung: Verwendung von Kanälen für Benutzeraktionen.
- Aktion: Erstellen Sie einen Kanal für Benutzeraktionen (z. B.
userActionChan := make(chan string)). - Logik:
- Der
handleInput-Handler sendet Aktionen wie"pause","seek_forward","speed_up"über den Kanal. - Die Hauptwiedergabeschleife (
playbackLoop) verwendet eineselect-Anweisung, um entweder auf den nächsten Frame-Tick oder auf eine neue Benutzeraktion zu warten.
- Der
- Vorteil: Entkoppelt die Eingabeverarbeitung von der Wiedergabelogik und reduziert die Sperrkonkurrenz, was zu einer reaktionsschnelleren Steuerung führt.
- Aktion: Erstellen Sie einen Kanal für Benutzeraktionen (z. B.
2.3 Fehlerbehandlung und Robustheit
- Problem: Fehler, die während der
ffmpeg-Extraktion auftreten, werden nicht an den Benutzer gemeldet, nachdem der Prozess gestartet wurde. - Empfehlung: Verbesserte Fehlerberichterstattung von
ffmpeg.- Aktion: Überprüfen Sie den Rückgabefehler von
ffmpegCmd.Wait()in der Goroutine, die auf das Ende vonffmpegwartet. - Logik: Wenn
ffmpegCmd.Wait()einen Fehler zurückgibt, bedeutet dies, dassffmpegmit einem Fehlercode beendet wurde. In diesem Fall sollte die Ausgabe, die imffmpegErr-Puffer gesammelt wurde, im Terminal protokolliert werden, um dem Benutzer eine klare Fehlermeldung zu geben (z. B. "Codec nicht gefunden", "Datei beschädigt").
- Aktion: Überprüfen Sie den Rückgabefehler von
2.4 Funktionserweiterungen
- Problem: Die Go-Version bietet keine flexiblen Skalierungsmodi wie das Shell-Skript (
fit,fill,stretch). - Empfehlung: Implementierung erweiterter Skalierungsoptionen.
- Aktion: Fügen Sie ein neues Befehlszeilen-Flag hinzu, z. B.
-scale <mode>. - Logik: Basierend auf dem gewählten Modus muss die
-vf-Option (Video-Filter) fürffmpegdynamisch erstellt werden. Dies erfordert ähnliche Berechnungen wie im Shell-Skript, um das Seitenverhältnis zu berücksichtigen:fit:scale=W:H:force_original_aspect_ratio=decreasefill:scale=W:H:force_original_aspect_ratio=increase,crop=W:Hstretch:scale=W:H
- Vorteil: Gibt dem Benutzer mehr Kontrolle über die Darstellung des Videos.
- Aktion: Fügen Sie ein neues Befehlszeilen-Flag hinzu, z. B.
2.5 Codequalität
- Problem: Globale Variablen für Konfiguration und Zustand machen den Code schwerer lesbar und testbar.
- Empfehlung: Verwendung von Konfigurations- und Zustandsstrukturen.
- Aktion:
- Führen Sie eine
Config-Struktur ein, die alle Befehlszeilenoptionen enthält. - Führen Sie eine
Player-Struktur ein, die den gesamten Wiedergabezustand (Mutex,isPaused,currentFrameIndexusw.) kapselt.
- Führen Sie eine
- Logik: Die
main-Funktion initialisiert dieConfig-Struktur und übergibt sie an dieplayVideo-Funktion. Diese wiederum erstellt einePlayer-Instanz. Zustandsänderungen erfolgen über Methoden auf demPlayer-Objekt (z. B.player.Pause(),player.Seek()), die die Sperrung intern verwalten. - Vorteil: Verbessert die Kapselung, Lesbarkeit und Wartbarkeit des Codes erheblich.
- Aktion:
hitvid v1.1.2
Modify the temporary directory creation logic:
- Try to use
/dev/shmfirst to get the best performance. - If the above method does not work, issue a warning and try to use
$HOME/tmp. If it does not exist, try to create it. - If neither of the above two methods is feasible, an error is reported.
The rest of the code is unchanged.
hitvid v1.1.1_Golang
Added a version written in Go language. Go is much faster than shell, and ffmpeg and chafa are built-in, no need to install, and it is faster.
Currently, the Go version is in the testing stage.
hitvid v1.1.1
Subject: feat: Enhance streaming playback, error handling, and quiet mode (v1.1.1)
This release introduces significant improvements to hitvid, focusing on more robust streaming playback, better error handling, and a refined user experience, especially when using the --quiet flag.
Key Changes & Improvements:
-
Dedicated FFmpeg Monitoring Subshell (
ffmpeg_monitor_subshell):- Old: FFmpeg progress monitoring and error logging were intertwined with the
extract_frames_daemonfunction, sometimes leading to cluttered output or less reliable error detection. - New: A new, dedicated
ffmpeg_monitor_subshellis introduced. This subshell runs in the background, specifically monitoring the FFmpeg process for health and logging any errors to a file. - Benefit: Decouples FFmpeg management from the main script flow, making the playback loop cleaner and more resilient. It also ensures FFmpeg errors are captured and reported even if the main script is busy rendering.
- Old: FFmpeg progress monitoring and error logging were intertwined with the
-
Improved
--quietMode Behavior:- Old: The
--quietflag suppressed some progress bars and interactive feedback, but not all, and some daemon messages could still appear. Interactive controls (like pause/seek) were also disabled in quiet mode. - New:
display_progress_barnow explicitly checks theQUIETflag, ensuring no progress bars are shown when quiet.render_chafa_daemonno longer prints verbose progress messages tostderrduring operation, respecting the quiet mode.- Crucially, interactive controls (Spacebar for pause/resume, arrow keys for seek/speed) now function even in
--quietmode. Only the visual feedback on the info line is suppressed. - The
qkey for quitting has been removed, standardizing onCtrl+Cfor exiting, which is universally handled by the improvedtrapmechanism.
- Benefit: Provides a truly "quiet" experience while retaining essential interactive control, offering a better user experience for those who prefer minimal output.
- Old: The
-
Enhanced Error Handling and Cleanup:
- Old: Cleanup was generally effective but could be improved, and
traphandling was less specific. - New:
- The
cleanupfunction now explicitly attempts to terminate the newFFMPEG_MONITOR_PIDin addition to FFmpeg and Chafa daemons. trapcommands are more specific (exit 130forINT/ Ctrl+C,exit 1forTERM/EXIT), providing clearer exit codes.- Warning messages during playback (e.g., "Frame missing") are now printed cleanly above the info line using
tput cupandtput el, preventing screen corruption.
- The
- Benefit: More robust and reliable termination of background processes, cleaner error reporting, and better overall script stability.
- Old: Cleanup was generally effective but could be improved, and
-
More Accurate Video Information Parsing:
- Old:
get_video_infosometimes struggled withN/Aor fractional duration/frame rate values fromffprobe, potentially leading to incorrectEXPECTED_TOTAL_FRAMES. - New: The logic for parsing
VIDEO_DURATION_FLOATandEXPECTED_TOTAL_FRAMEShas been refined to better handle variousffprobeoutputs (decimal, fractional, N/A), providing more accurate frame counts. - Benefit: Improves the reliability of frame extraction and playback duration, especially for videos with non-standard metadata.
- Old:
-
Streamlined Playback Initialization:
- Old: The
tput smcup; tput civis; clearcommands were executed early, potentially clearing initial FFmpeg loading messages in stream mode. - New: These screen manipulation commands are now executed after any initial loading messages (including the FFmpeg progress bar from the monitor subshell) have been displayed and cleared.
- Benefit: Ensures a smoother transition from loading to playback, preventing flicker or premature screen clearing.
- Old: The
This update significantly enhances hitvid's stability, user experience, and internal architecture, making it more reliable and pleasant to use.
hitvid v1.1.0
hitvid Version Improvement Technical Report
Project Name: hitvid - Terminal Video Player
Version: From v1.0.2 to v1.1.0
Date: June 1, 2025
Core Maintainer: Hitmux
1. Overview
hitvid v1.1.0 represents a significant iteration in the hitvid project concerning performance and architectural stability. The primary goal of this version is to address the synchronization issues between Chafa rendering and video playback present in v1.0.2, and to significantly enhance the user experience, particularly playback fluidity under high frame rate and resource-constrained environments. By introducing Chafa rendering daemonization and optimizing the frame processing pipeline, we have successfully decoupled the rendering logic from the main playback loop, achieving a more truly streaming playback experience.
2. Key Improvements
2.1 Chafa Rendering Architecture Refactor
This is the most crucial improvement in v1.1.0.
-
v1.0.2(Old Architecture):
Inv1.0.2, Chafa frame generation was initiated in the background as a parallel process via therender_all_chafa_frames_parallel &function. The main playback functionplay_chafa_framesrelied on these background rendering processes to complete the generation of text frames. Although background execution was used, implicit synchronization points (via the file system) between the rendering and playback processes, and the eventualwait "$RENDER_PID"command, could still lead to blocking and stuttering during playback, especially if rendering speed could not keep up with playback speed.# v1.0.2 Core Rendering Startup Logic render_all_chafa_frames_parallel & RENDER_PID=$! # ... play_chafa_frames # ... wait "$RENDER_PID" # Wait for rendering process to complete
-
v1.1.0(New Architecture):
v1.1.0introduces therender_chafa_daemonfunction, fundamentally changing how Chafa frames are generated. Now,render_chafa_daemonoperates as an independent, long-running daemon process (CHAFA_RENDER_DAEMON_PID). It continuously reads the latest JPG frames from theJPG_FRAMES_DIR(generated by FFmpeg) and converts them in real-time into Chafa text frames, storing them inCHAFA_FRAMES_DIR.The main playback function
play_chafa_framesno longer directly waits for rendering completion. Instead, it independently reads available text frames fromCHAFA_FRAMES_DIRfor display. This design achieves complete decoupling of rendering and playback, withplay_chafa_framesacting as a "consumer" andrender_chafa_daemonas a "producer."# v1.1.0 Core Rendering Startup Logic render_chafa_daemon "$EXPECTED_TOTAL_FRAMES" "$FFMPEG_PID" # Start the daemon # ... play_chafa_frames "$EXPECTED_TOTAL_FRAMES" # Play independently, reading from files output by the daemon # ... # At the end of playback, clean up the daemon if [[ -n "$CHAFA_RENDER_DAEMON_PID" ]] && ps -p "$CHAFA_RENDER_DAEMON_PID" > /dev/null; then kill -TERM "$CHAFA_RENDER_DAEMON_PID" wait "$CHAFA_RENDER_DAEMON_PID" 2>/dev/null fi
-
Technical Advantages:
- High Throughput & Low Latency: The rendering process can work continuously, unblocked by the playback process, maximizing Chafa conversion throughput. The playback process can consume the latest rendered frames immediately, reducing display latency.
- Playback Fluidity: Eliminates playback stuttering caused by rendering bottlenecks in the old version, achieving smoother video streams.
- Improved Resource Utilization: The rendering process can continuously utilize idle CPU cycles in the background, improving overall system resource efficiency.
- Robustness: A crash in the rendering process no longer directly leads to the failure of the main playback logic, enhancing application stability.
2.2 First Frame Pre-rendering Optimization
To provide more immediate visual feedback at the start of video playback, v1.1.0 improves the pre-rendering logic for the first frame.
-
v1.0.2: Simply calledrender_single_frame_for_xargs "$first_jpg_basename"and expected it to complete quickly. The first frame output went directly to standard output. -
v1.1.0:- Added a loop (
wait_first_jpg_count) to wait for the first JPG frame to be generated, ensuring the JPG file exists before attempting to render it. - Redirects the Chafa rendering result of the first frame directly to the
first_txt_to_createfile, rather than standard output. This ensures the first text file is available before playback. - Provides more explicit error and warning messages, e.g., when the FFmpeg process fails to generate the first JPG frame in time.
# v1.1.0 First Frame Pre-rendering Logic wait_first_jpg_count=0 while [ ! -f "$first_jpg_to_check" ] && [ "$wait_first_jpg_count" -lt 50 ] && [[ -n "$FFMPEG_PID" ]] && ps -p "$FFMPEG_PID" >/dev/null; do sleep 0.01 wait_first_jpg_count=$((wait_first_jpg_count + 1)) done if [ -f "$first_jpg_to_check" ]; then (chafa $CHAFA_OPTS_RENDER "$first_jpg_to_check" > "$first_txt_to_create") if [ $QUIET -eq 0 ] && [ -f "$first_txt_to_create" ]; then echo "First frame pre-rendered to $first_txt_to_create."; fi elif [ $QUIET -eq 0 ]; then echo "Warning: Could not pre-render first frame quickly. FFmpeg PID: ${FFMPEG_PID:-N/A}. File: $first_jpg_to_check" fi
- Added a loop (
-
Technical Advantages: Reduces the startup latency of video playback, improving the perceived responsiveness for the user.
2.3 Process ID (PID) Management and Cleanup
v1.1.0 introduces clearer PID management for background processes.
-
v1.0.2: Primarily focused onRENDER_PID. -
v1.1.0: Explicitly defines and usesFFMPEG_PIDandCHAFA_RENDER_DAEMON_PIDas two key background process IDs. At the end of the script,kill -TERMandwaitcommands are used to ensure these background processes are correctly terminated and cleaned up, preventing zombie processes. -
Technical Advantages: Enhances script robustness and resource management capabilities, reducing the risk of system resource leaks.
3. Future Work
- "preload" Playback Mode: The
PLAY_MODE="preload"option is commented out in the code but not yet implemented. Future work could include implementing this mode, where all Chafa frames are fully rendered before playback begins, suitable for short videos or scenarios requiring the highest possible fluidity. - More Granular Error Handling: Enhance error handling for abnormal exits of FFmpeg and Chafa processes, providing more user-friendly error messages.
- Interactive Control Optimization: Further optimize the responsiveness and user experience of playback controls (pause, fast-forward, rewind).
hitvid v1.0.2
hitvid Script Modification Report
Overview
The new version of the hitvid script introduces significant functional enhancements and user experience (UX) optimizations over its predecessor. Key changes include the introduction of interactive playback controls (pause, seek forward/backward, speed adjustment), optimized frame processing performance (e.g., attempting to use the RAM disk /dev/shm for temporary file storage, FFmpeg pre-scaling), considerably improved user feedback mechanisms (such as progress bars for time-consuming operations), along with several code refactorings and enhancements to error handling.
Detailed Change Points
-
New Interactive Playback Controls
- Scope of Impact: Core logic of
play_chafa_framesfunction,show_helpmessage, new global variables. - Specific Changes:
- In
play_chafa_frames, user input is read non-blockingly usingread -t. - Supported Controls:
Spacebar: Pause/Resume playback.Right Arrow Key: Seek forward (bySEEK_SECONDS, default 5 seconds).Left Arrow Key: Seek backward (bySEEK_SECONDS).Up Arrow Key: Increase playback speed.Down Arrow Key: Decrease playback speed.
- New related global variables:
PAUSED: Flags the paused state.ORIGINAL_FPS: Stores the user-defined or default original extraction frame rate.CURRENT_FPS_MULTIPLIER_INDEX: Index to control the playback speed multiplier.PLAYBACK_SPEED_MULTIPLIERS: Defines an array of available playback speed multipliers (e.g., 0.25x, 0.5x, 1.0x, 2.0x).SEEK_SECONDS: Defines the seek duration in seconds.
show_help: Added an "Interactive Controls" section to explain these new features.
- In
- Purpose: Greatly enhances user flexibility and control while watching videos.
- Scope of Impact: Core logic of
-
Performance Optimizations
- Temporary File Storage Optimization (
setup_temp_dir):- Prioritizes creating the temporary directory in
/dev/shm(tmpfs, a memory-based file system). If successful, this can significantly improve the read/write speed of frame files, especially for many small files. - If
/dev/shmis unavailable or creation fails, it falls back to the traditional/tmpdirectory.
- Prioritizes creating the temporary directory in
- FFmpeg Pre-scaling (
extract_frames):- New constants
CHAR_PIXEL_WIDTH_APPROXandCHAR_PIXEL_HEIGHT_APPROXare introduced to estimate pixel dimensions corresponding to character cells. - Based on the target display character width (
WIDTH) and height (HEIGHT), calculates target pixel dimensions for FFmpeg pre-scaling. - Adds a
scalefilter (and potentiallycropdepending onSCALE_MODE) to theffmpegcommand's-vf(video filter) option. This allows FFmpeg to scale frames to a size close to what Chafa requires during extraction. - Purpose: Reduces Chafa's scaling workload, potentially improving Chafa's rendering speed and the visual consistency of the final output.
- New constants
- Stream Mode First-Frame Pre-rendering (Main Execution Block for
streammode):- In
streammode, the script now attempts to synchronously render the first frame of the video before launching the background process to render the remaining frames. - Purpose: Reduces the waiting time for the user to see the first frame in stream mode, improving the startup experience.
- In
- Temporary File Storage Optimization (
-
User Experience (UX) Enhancements
- Progress Bar Display:
- New helper function
display_progress_baradded to generate and display text-based progress bars. extract_frames: In non-quiet mode, uses theffmpeg -progressoption to output progress information to a file. The script reads this file to display a real-time progress bar for FFmpeg frame extraction.render_all_chafa_frames_parallel: Inpreloadmode and non-quiet mode, displays a rendering progress bar by polling the number of generated Chafa text frames.play_chafa_frames: The information line during playback now includes a more intuitive progress bar showing the current playback position.
- New helper function
- Clarification of FPS Parameter Semantics:
- The help description for the
--fpscommand-line option is updated to "Set extraction frames per second." - The
ORIGINAL_FPSvariable is introduced to store this extraction frame rate. The actual frame delay during playback is calculated based on this original FPS and the current playback speed multiplier.
- The help description for the
- More Detailed Output Information:
get_video_info: Output now includes the total number of input frames in the video (if provided by ffprobe).extract_frames: Outputs the video filter options used by FFmpeg.- Richer informational messages for various stages (e.g., temporary directory location, renderer PID).
- Terminal State Restoration (
cleanup):- Added the
stty sanecommand to ensure terminal settings are restored to a "sane" known-good state upon script exit (including abnormal exits).
- Added the
- Help Message (
show_help):- Updated descriptions for
-f, --fpsand-s, --scaleoptions for better accuracy. - Added a note about how
-q, --quietmode affects interactive feedback.
- Updated descriptions for
- Progress Bar Display:
-
Functional Improvements & Refactoring
- Dependency Check (
check_dependencies):- Added a dependency check for
awk, as it's now used for floating-point arithmetic (e.g., calculating frame delay, comparing FPS values).
- Added a dependency check for
- Argument Parsing and Validation:
- The file existence check for
VIDEO_PATHnow correctly handles network stream URLs (e.g.,http*,ftp*,rtmp*) and standard input (-), for which local file existence should not be checked. - Parameter validations involving floating-point numbers (e.g.,
FPS > 0,FPS > MAX_FPS) are now implemented usingawk, which is more suitable for floating-point operations than Bash built-ins. - If an unknown option is provided, the script now shows the help message instead of directly exiting with an error.
- The file existence check for
- Chafa Options and Environment:
- The definition of the
CHAFA_OPTS_RENDERvariable is moved to the main execution flow, afterextract_framesand before callingrender_all_chafa_frames_parallelorrender_single_frame_for_xargs. - In the
render_all_chafa_frames_parallelfunction, whenxargsis used to executerender_single_frame_for_xargs, variables likeCHAFA_OPTS_RENDER,JPG_FRAMES_DIR,CHAFA_FRAMES_DIR, andQUIETare explicitlyexported to ensure sub-shells correctly inherit these environment variables.
- The definition of the
- FFmpeg Invocation (
extract_frames):- The
ffmpegcommand now includes the-nostdinoption to prevent it from accidentally consuming standard input, which is crucial for the subsequent interactive key reading.
- The
- Playback Timing (
play_chafa_frames):- The calculation of the
sleepduration after each frame now considers the actual processing time for that frame (reading file,catoutput, etc.), making the frame interval closer to the target frame rate. frame_delaycalculation is now based onORIGINAL_FPS * PLAYBACK_SPEED_MULTIPLIER.
- The calculation of the
- Error Handling:
- In stream mode, if the background renderer process (
RENDER_PID) terminates unexpectedly and the required frame file is missing, a more specific error message is displayed before exiting.
- In stream mode, if the background renderer process (
- Dependency Check (
-
Code Cleanup & Minor Adjustments
- Removed the cleanup logic for
XARGS_FIFOfrom thecleanupfunction, as it was mentioned in the old version but not actually used. - In
render_single_frame_for_xargs, when the source JPG file doesn't exist, the check forQUIETis removed, and it directly returns an error code (as warnings go to stderr, and the progress bar is the primary user feedback). - Other minor updates to comments and code formatting for improved readability.
- Removed the cleanup logic for
Conclusion
The new version of hitvid, by introducing interactive controls, optimizing performance, and improving the user interface, significantly enhances its usability and user-friendliness as a terminal video player. These modifications make the script more powerful, easier to operate, and provide a smoother experience.
hitvid v1.0.1
hitvid v1.0.1 Modification Report: Terminal Alternate Screen Buffer & Security Enhancements
The main contents of this modification include the implementation of the "alternate screen buffer" feature, addressing potential security vulnerabilities, enhancing code robustness, and adjusting default options to improve user experience.
I. Terminal Alternate Screen Buffer Feature Implementation
Goal:
Modify the hitvid script to play videos in the terminal's "alternate screen buffer." This provides a "full-screen" application-like experience where the video player occupies the entire terminal window without affecting previous command output. When the player exits, the original terminal screen and its scroll history will be restored.
Summary of Changes:
The core changes involve using tput commands to manage the terminal's screen buffers:
tput smcup: Switches to the alternate screen buffer.tput rmcup: Switches back to the normal screen buffer.
These commands have been integrated into the script's playback and cleanup routines.
Detailed Modifications:
-
play_chafa_frames()function:- Added
tput smcup: At the beginning of this function,tput smcupis now called. This command instructs the terminal to switch to its alternate screen buffer before displaying any video playback content (such as the initialclearor the frames themselves). - Context of
clearcommand: The existingclearcommand in this function now clears the alternate screen buffer, preparing it for video playback. - Removed Redundant Cleanup:
tput cnorm(restore cursor) and theecho -e "\nPlayback complete."at the end of the function (which might implicitly clear the screen if it's the last output) have been adjusted or are now effectively handled by thecleanupfunction upon exit, ensuring a clean switch back to the normal screen. The "Playback complete" message now briefly appears on the alternate screen's info line, thencleanuptakes over.
- Added
-
cleanup()function:- Added
tput rmcup: This command has been added to thecleanupfunction. It is responsible for switching the terminal from the alternate screen buffer back to the normal screen buffer. - Order of Operations:
tput rmcupis called aftertput cnorm(restoring the cursor). This ensures the cursor is visible first, then the screen is switched. Any subsequentechocommands within thecleanupfunction (e.g., "Cleaning up temporary files...") will now display on the restored normal terminal screen.
- Added
-
trapcommand (insetup_temp_dir()):- Modified to include
EXIT: Thetrapcommand has been updated totrap "cleanup; exit" INT TERM EXIT. - Adding
EXITis crucial. It ensures that thecleanupfunction (and thustput cnormandtput rmcup) is executed not only when the script is interrupted (e.g.,INTviaCtrl+C, orTERMviakill) but also when the script terminates normally (e.g., when video playback completes and the script reaches its natural end or executes anexit 0command).
- Modified to include
Results:
- When
hitvidstarts, initial messages (e.g., "Analyzing video file...") are displayed on the standard terminal screen. - Before video playback begins, the terminal switches to an alternate screen. The video will play within this "new" screen.
- When playback ends or the script is interrupted, the
cleanupfunction is triggered. This function restores the cursor, switches back to the normal terminal screen (restoring all prior output and scroll history), and then deletes temporary files. - The user experience is now similar to applications like
vim,nano, orless, which use the alternate screen buffer to provide a dedicated interface without interfering with existing terminal content.
II. Security Vulnerability Fixes and Code Enhancements
This section details the security fixes and general code enhancements made to the hitvid script. The primary goals were to address potential command injection vulnerabilities and TOCTOU (Time-of-Check, Time-of-Use) race conditions in temporary file handling.
Overview of Addressed Vulnerabilities:
- Command Injection: The original script directly passed user-controlled input (
$VIDEO_PATH) as arguments to external commands (ffmpeg,ffprobe) without proper separation. If an attacker could control the value ofVIDEO_PATH(e.g., by crafting a filename starting with-), this could allow them to inject arbitrary command-line options or even execute arbitrary commands. - TOCTOU (Time-of-Check, Time-of-Use) Race Condition: The temporary directory created with
mktemp -dwas subsequently removed usingrm -rf "$TEMP_DIR". In a multi-user environment, a brief window exists between directory creation and the execution of thermcommand, which a malicious actor could exploit to replace$TEMP_DIRwith a symlink pointing to a sensitive directory (e.g.,/home/user/.ssh), leading to unintended file deletion.
Detailed Modifications:
1. Command Injection Mitigation
- Issue: The
ffprobe,ffmpeg, andchafacommands were vulnerable to argument injection if$VIDEO_PATHor$jpg_pathcontained malicious characters or started with a hyphen (-). - Solution:
- In the
ffprobeandffmpegcommands (get_video_infoandextract_framesfunctions),--(double-hyphen) has been added before the$VIDEO_PATHargument. The--convention tells the command-line parser that all subsequent arguments are non-options (i.e., filenames), preventing them from being interpreted as command flags. - Similarly, in the
chafacommand (render_single_frame_for_xargsfunction),--has also been added before the$jpg_pathargument for consistency and best practice, even though$jpg_pathis internally generated.
- In the
2. TOCTOU Vulnerability Mitigation in Temporary Directory Handling
- Issue: The
rm -rf "$TEMP_DIR"command in thecleanup()function was vulnerable to TOCTOU attacks. - Solution:
- In
setup_temp_dir():- Immediately after creating the temporary directory with
mktemp -d,chmod 700 "$TEMP_DIR"has been added. This sets permissions to owner-only read, write, and execute, significantly reducing the window and opportunity for other users to tamper with the directory (e.g., by creating symlinks) before it's used or deleted.
- Immediately after creating the temporary directory with
- In
cleanup():- Robust validation has been implemented before executing
rm -rf:if [ -d "$TEMP_DIR" ] && [[ "$TEMP_DIR" == /tmp/hitvid.* ]]. This check ensures that$TEMP_DIRstill points to an actual directory and its path matches the expected pattern generated bymktemp(/tmp/hitvid.XXXXXX). If the path has been tampered with or is not a directory, a warning will be issued, and the deletion operation will be skipped. - Used
rm -rf -- "$TEMP_DIR": Added--to thermcommand to prevent$TEMP_DIR(if maliciously modified to start with-) from being interpreted as an option forrm. - To be foolproof, the
TEMP_DIRvariable is now emptied after cleanup (TEMP_DIR=""). - For consistency,
--has also been added forrm -f -- "$XARGS_FIFO", althoughXARGS_FIFOis not actually used in the currently provided script.
- Robust validation has been implemented before executing
- In
3. General Code Enhancements (Non-Security Related but Improves Robustness)
- Improved Argument Parsing: The argument parsing loop has been made more robust, capable of handling various input scenarios, including the
--option separator. - Enhanced Input Validation: More specific error messages and
show_helpcalls have been added for invalid command-line options and arguments, making the script easier to use and debug. ffmpegExit Status Check: A check for theffmpegcommand's exit status has been added inextract_framesto provide clearer error reporting if frame extraction fails.- Use of
printf: Someecho -ecalls have been replaced withprintfto improve portability across different shell environments, asecho -ebehavior can vary. - URL Support: Explicitly stated that
VIDEO_PATHcan be anhttporhttpsURL, asffmpegsupports this functionality.
Impact and Benefits:
These modifications significantly enhance the security of the hitvid script by preventing common attack vectors such as command injection and TOCTOU race conditions. The general code enhancements also make the application more robust, reliable, and user-friendly. Users can now run the script with greater confidence, knowing it is less susceptible to malicious input or environmental manipulation.
III. Default Option Modifications
Please compare the changes yourself, as they are not detailed here.
hitvid v1.0.0
hitvid Terminal Video Player Summary
hitvid is a Bash script-based terminal video player that leverages ffmpeg to extract video frames and chafa to render them as ASCII art, enabling direct video playback within your terminal.
Key Features
- In-Terminal Playback: Watch videos directly in your terminal window.
- Multiple Rendering Options: Supports custom FPS, scaling modes, color counts, dithering algorithms, and character sets.
- Two Playback Modes:
preload(Default): Extracts and converts all video frames into Chafa text frames before playback begins, offering the smoothest experience but with a longer initial processing time.stream: Starts playback while converting frames in the background. This allows for quicker initiation but might cause stuttering if rendering can't keep up.
- Parallel Processing: Utilizes multi-core CPUs to speed up frame rendering.
- Loop Playback and Quiet Mode are supported.
- Automatic Cleanup of temporary files upon script exit.
Dependencies
You'll need ffmpeg, chafa, and tput installed. nproc and xargs are recommended for optimized performance.
Usage
Run the script using ./hitvid.sh [VIDEO_PATH] [OPTIONS]. It supports both local video file paths and direct video URLs.
Core Workflow
- General Steps: Parses arguments, checks dependencies, sets up a temporary directory, retrieves video info, and extracts JPG video frames using
ffmpeg. preloadMode: All JPG frames are rendered in parallel into Chafa text frames before playback starts.streamMode: Background parallel rendering of Chafa text frames occurs simultaneously with playback; the player waits if a required frame isn't ready.- Cleanup: A
trapmechanism ensures automatic deletion of temporary files and restoration of terminal settings upon script exit.
Notes and Troubleshooting
- Performance: High-resolution or high-bitrate videos may be choppy, and terminal rendering capabilities can be a bottleneck.
- Terminal Compatibility: Best results are seen with terminals that support ANSI escape sequences well (e.g.,
gnome-terminal,konsole,iTerm2). - Font: Monospaced fonts generally provide better character art display.
- Temporary Files: Ensure sufficient space in your
/tmpdirectory. --threadsOption: Setting this to your CPU core count is usually optimal.- Stuttering in Stream Mode: Try lowering FPS, reducing colors, increasing threads, or switching to
preloadmode. - Errors: Verify that all dependencies are installed and in your
PATH, and check for corrupted video files.