BlackVideo Mini Player

March 20, 2026 · View on GitHub

Visitors

2.4.0

New update 2.4.0 is here. This release adds cloud LLM caption generation (Claude, OpenAI, Gemini, DeepSeek, Grok), sprite thumbnail hover preview on the seek bar, a welcome/standalone mode with drag-and-drop, and a GitHub auto-updater that checks for new releases in the background.

Sample Files Generated by Whisper

The SRT files below were generated using the offline caption feature (ggml-base model).

VideoLanguageSRT
Elon Musk's Work Ethics Will Give You GoosebumpsEnglishDownload
AURORA - Cure For Me (1080p)EnglishDownload
BTS - Boy With Luv (feat. Halsey)KoreanNot generated — ggml-base does not support Korean. Use ggml-large-v3.
Screenshot

BlackVideo Mini Player

Lightweight cross-platform video player (Ada + SDL2 + FFmpeg). Support player for the BlackVideo. Works standalone via CLI, drag-and-drop, or right-click on any video file.


Screenshot
Screenshot
Screenshot

What's New in v2.4.0

FeatureDescription
Welcome / Standalone modeLaunch with no argument — shows a welcome screen with Open File button and full drag-and-drop support
Cloud LLM captionsRight-click → choose Claude, OpenAI, Gemini, DeepSeek, or Grok to generate a timed SRT using a cloud AI
API key overlaySecure masked text-input dialog to enter and save API keys per provider (stored in %APPDATA%\BlackVideo\keys.cfg)
Sprite thumbnail previewHover over the seek bar to see a JPEG frame thumbnail popup — extracted by ffmpeg in the background
Auto-updaterBackground thread checks latest.json on GitHub at startup; shows an update badge and download overlay when a newer version is available
Whisper progress %Live progress bar during caption generation via stderr pipe
Hot-load videoDrop or open a new video while already playing — no restart required

File Structure

blackvideo-mini-player/

├── src/
│   ├── main.adb                  ← Entry point + .env loader
│   ├── player.ads / .adb         ← Core orchestrator + event loop
│   ├── video_decoder.ads / .adb  ← FFmpeg decode pipeline
│   ├── renderer.ads / .adb       ← SDL2 texture rendering (letterbox)
│   ├── audio.ads / .adb          ← SDL2 audio callback + volume/mute/flush
│   ├── ui_overlay.ads / .adb     ← Ada wrapper for the C UI overlay
│   ├── srt_parser.ads / .adb     ← SRT subtitle file parser
│   ├── whisper_bridge.ads / .adb ← Whisper.cpp offline caption bridge
│   ├── llm_bridge.ads / .adb     ← Cloud LLM caption bridge (5 providers)
│   ├── thumb_cache.ads / .adb    ← Seek-bar sprite thumbnail cache
│   ├── updater.ads / .adb        ← GitHub release auto-updater
│   └── utils.ads / .adb          ← Base_Name, Format_Time

├── csrc/                         ← C sources compiled separately (not scanned by gprbuild)
│   ├── ui_overlay.c              ← SDL2-drawn control bar, context menu, overlays,
│   │                                thumbnail popup, API key input dialog
│   ├── process_helpers.c         ← CreateProcess async launcher + stderr pipe
│   ├── thumb_preview.c           ← JPEG thumbnail loader (Windows WIC) + SDL popup
│   └── llm_client.c              ← WinINet HTTPS GET/POST for LLM + updater

├── bindings/
│   ├── ffmpeg/
│   │   ├── ffmpeg-avutil.ads
│   │   ├── ffmpeg-avcodec.ads
│   │   ├── ffmpeg-avformat.ads
│   │   ├── ffmpeg-swscale.ads
│   │   └── ffmpeg-swresample.ads
│   └── sdl2/
│       ├── sdl.ads
│       ├── sdl-video.ads
│       ├── sdl-video-windows.ads/adb
│       ├── sdl-video-renderers.ads/adb
│       ├── sdl-video-textures.ads/adb
│       ├── sdl-events.ads/adb           ← flat byte extractor + SDL_TEXTINPUT support
│       ├── sdl-events-keyboards.ads
│       └── sdl-audio.ads

├── tools/
│   └── context_menu/
│       ├── install_context_menu.bat
│       ├── install_context_menu.reg
│       ├── uninstall_context_menu.bat
│       ├── uninstall_context_menu.reg
│       ├── install_linux.sh
│       ├── blackvideo-player.desktop
│       └── install_macos.sh

├── include/
│   └── stb_image.h         ← Placeholder (thumbnail decoding uses Windows WIC)

├── lib/
│   ├── include/      ← FFmpeg + SDL2 headers
│   └── *.a           ← Import libraries

├── build/            ← Compiled output + runtime DLLs
│   └── cache/        ← Sprite thumbnail JPEG cache (auto-created)

├── scripts/
│   ├── build.bat
│   └── build.sh

├── latest.json             ← Auto-updater manifest (place in repo root)
├── .env.example
├── WHISPER_SETUP.md
└── blackvideo_player.gpr

Keyboard Controls

KeyAction
SPACEPlay / Pause
Seek −5 seconds
Seek +5 seconds
Volume +10
Volume −10
MMute / Unmute
LLoop toggle
FFullscreen toggle
ESC / QQuit

Playback Controls (UI Bar)

ControlAction
Seek barClick or drag to seek
Seek bar hoverShows sprite thumbnail preview at that position
⏮ PrevSeek to start
⏯ Play/PauseToggle playback
⏭ NextJump to near end
🔁 LoopToggle loop
🔊 VolumeMute/unmute
1.0x SpeedCycle 0.5× / 1.0× / 1.5× / 2.0×
⛶ FullscreenToggle fullscreen
⋮ MenuOpen context menu

Right-click anywhere on the video to open the context menu.


Context Menu

ItemAction
Open FileOpen a video via dialog (works from welcome screen too)
Subtitle: Off / Track NToggle subtitles off
Track 1 / 2 / 3Load an .srt subtitle file into that slot
Generate Captions (Whisper)Offline caption generation via whisper.cpp
Translate to English (Whisper)Offline translation + caption via whisper.cpp
Captions: ClaudeCloud LLM caption via Anthropic Claude
Captions: OpenAICloud LLM caption via OpenAI GPT
Captions: GeminiCloud LLM caption via Google Gemini
Captions: DeepSeekCloud LLM caption via DeepSeek
Captions: GrokCloud LLM caption via xAI Grok
Clear Thumbnail CacheDelete cached seek-bar thumbnails for this video
Check for UpdatesManually trigger the GitHub version check

Subtitles

Loading a subtitle file manually

Right-click → Track 1 / 2 / 3 → pick an .srt file. The track label updates to the filename and the active track is marked.

Generating captions with Whisper (offline)

Right-click → Generate Captions (Whisper)

Uses whisper.cpp entirely offline — no internet, no API key. FFmpeg extracts a 16 kHz mono WAV, whisper-cli.exe runs in the background, and the resulting .srt auto-loads into Track 1. A live progress bar shows percentage completion.

Translating subtitles to English

Right-click → Translate to English (Whisper)

Whisper's --translate flag transcribes and outputs English regardless of spoken language.

Translation target: Currently English only. Multi-language targets are planned for a future release.

Generating captions with a cloud LLM

Right-click → Captions: Claude / OpenAI / Gemini / DeepSeek / Grok

Two-step flow:

  1. Whisper-tiny generates a raw transcript (~30s for a 60s clip)
  2. The transcript is sent to the chosen LLM with a timing prompt
  3. The LLM returns a properly timed SRT, saved beside the video and auto-loaded into Track 2

First use: An API key dialog appears. Type or paste your key — it is masked on screen and saved to %APPDATA%\BlackVideo\keys.cfg. Press Enter or click OK to save. Click Cancel, the X button, or press Esc to dismiss without saving.

ProviderKey source
Claudeconsole.anthropic.com
OpenAIplatform.openai.com
Geminiaistudio.google.com
DeepSeekplatform.deepseek.com
Grokconsole.x.ai

Whisper setup (quick reference)

Place these files in build\ beside blackvideo-player.exe:

build\
├── blackvideo-player.exe
├── whisper-cli.exe
├── whisper.dll
├── ggml.dll
├── ggml-base.dll
├── ggml-cpu.dll
└── models\
    └── ggml-base.bin

ffmpeg.exe must be on your PATH or placed in build\ for audio extraction and thumbnail generation.

See WHISPER_SETUP.md for the full guide.


Sprite Thumbnail Preview

Hovering over the seek bar shows a 160×90 px JPEG popup at that position. Thumbnails are extracted in the background by ffmpeg (one frame per 10 seconds) and cached in build\cache\<video-hash>\. Right-click → Clear Thumbnail Cache to wipe the cache for the current video.


Auto-Updater

A background thread fetches latest.json from the repo root at startup. If a newer version is found, an update badge appears on the menu button. Right-click → Check for Updates to see the version notes and open the download page. Uses WinINet — no extra DLL needed.

{
  "version":      "2.4.0",
  "release_url":  "https://github.com/BlackBlazent/blackvideo-mini-player/releases/tag/v2.4.0",
  "download_url": "https://sourceforge.net/.../download",
  "notes":        "Standalone mode, sprite preview, LLM captions, auto-updater"
}

Building

Windows

Prerequisites

  1. Install Alire (GNAT + gprbuild): alr toolchain --select
  2. SDL2 dev libs (MinGW)
  3. SDL2_ttf dev libs
  4. FFmpeg shared builds (win64-lgpl)
  5. Copy headers + .a libs into lib/

Download the pre-assembled lib/ and build/ setup for Windows ✨

cd blackvideo-mini-player
scripts\build.bat
build\blackvideo-player.exe
build\blackvideo-player.exe "C:\Videos\movie.mp4"

Linux

sudo apt install gnat gprbuild \
    libsdl2-dev libsdl2-ttf-dev \
    libavcodec-dev libavformat-dev libavutil-dev \
    libswscale-dev libswresample-dev

chmod +x scripts/build.sh && ./scripts/build.sh
./build/blackvideo-player /path/to/video.mp4

macOS

brew install gnat gprbuild sdl2 sdl2_ttf ffmpeg
chmod +x scripts/build.sh && ./scripts/build.sh
./build/blackvideo-player /path/to/video.mp4

Right-Click Integration

Windows (Run as Administrator)

tools\context_menu\install_context_menu.bat

Adds "Open with BlackVideo Player" for: .mp4 .mkv .avi .mov .wmv .webm .flv .m4v .mpg .mpeg .ts

To remove: tools\context_menu\uninstall_context_menu.bat

Linux

chmod +x tools/context_menu/install_linux.sh
./tools/context_menu/install_linux.sh

macOS

chmod +x tools/context_menu/install_macos.sh
./tools/context_menu/install_macos.sh

Tauri v2 Integration

"bundle": {
  "externalBin": ["binaries/blackvideo-player"],
  "resources": ["binaries/SDL2.dll", "binaries/SDL2_ttf.dll",
    "binaries/avcodec-62.dll", "binaries/avformat-62.dll",
    "binaries/avutil-60.dll", "binaries/swscale-9.dll",
    "binaries/swresample-6.dll"]
}
#[tauri::command]
fn open_video(path: String) {
    Command::new_sidecar("blackvideo-player")
        .expect("sidecar not found")
        .args([path])
        .spawn()
        .expect("failed to launch player");
}

Required Files

DLLs — place in build\

DLLSource
SDL2.dllSDL2 MinGW release
SDL2_ttf.dllSDL2_ttf-devel-2.0.12-VC
libfreetype-6.dllBundled with SDL2_ttf-devel-2.0.12-VC
zlib1.dllBundled with SDL2_ttf-devel-2.0.12-VC
avcodec-62.dllFFmpeg shared build
avdevice-62.dllFFmpeg shared build
avfilter-11.dllFFmpeg shared build
avformat-62.dllFFmpeg shared build
avutil-60.dllFFmpeg shared build
swresample-6.dllFFmpeg shared build
swscale-9.dllFFmpeg shared build

Optional Whisper DLLs:

DLLSource
whisper.dll ggml.dll ggml-base.dll ggml-cpu.dllwhisper-bin-x64.zip

Headers — lib/include/

libavcodec/ libavdevice/ libavfilter/ libavformat/ libavutil/ libswresample/ libswscale/ SDL2/

Import Libraries — lib/

libavcodec.a libavdevice.a libavfilter.a libavformat.a libavutil.a libSDL2.a libSDL2main.a libSDL2_ttf.dll.a libswresample.a libswscale.a


Design Notes

Flat byte extraction for SDL events: Ada's discriminated unions cannot safely map to C anonymous unions without Unchecked_Union. The flat Raw_Bytes + offset extractors in SDL.Events are simpler and portable. SDL_TEXTINPUT events are handled the same way, enabling the API key input dialog.

csrc/ vs src/: GPRbuild compiles every file in src/ as Ada. C files live in csrc/ to stay invisible to GPRbuild; build.bat compiles them with gcc and passes the .o files directly to the linker.

Thumbnail decoding — Windows WIC: thumb_preview.c uses wincodec.dll (built into Windows 7+) to decode JPEGs. No stb_image.h download needed. Falls back to SDL_image on Linux/macOS.

LLM two-step flow: Whisper-tiny generates a raw transcript, which is sent to the cloud LLM with a timing prompt. The LLM returns a formatted SRT. Providers with native audio support (OpenAI, Gemini) can skip the transcript step.

Audio re-init on hot-load: Audio.Stop closes the SDL audio device. Open_Video calls Audio.Init to re-open it before starting playback on the new video, ensuring audio always works after drag-and-drop or file dialog.

Auto-updater thread safety: The version check runs on a CreateThread background thread (Convention => Stdcall). The result flag is written once and polled each frame by the main loop — no mutex needed.

Letterbox rendering: Renderer.Fit_Rect computes scale = min(win_w/vid_w, win_h/vid_h) and centres the video with black bars at any window size.


Contributing

  1. Fork the repository and create a new branch
  2. Make your changes and commit
  3. Push and open a pull request

Please read CONTRIBUTING.md for guidelines.

License

MIT License — see LICENSE for details.