143 lines
7.6 KiB
Markdown
143 lines
7.6 KiB
Markdown
# terebi
|
|
|
|
A native macOS player for local media, YouTube videos, and resolved Miruro streams, with compact mode, saved playback positions, and Chromecast support.
|
|
|
|
## Build and run
|
|
|
|
Requires macOS 15+, Xcode command-line tools with Swift 6, Python 3.9+, and these build tools:
|
|
|
|
```sh
|
|
brew install pkg-config meson ninja
|
|
# Intel Macs also need: brew install nasm
|
|
make
|
|
make run
|
|
```
|
|
|
|
The first build downloads pinned dependencies. Build natively on Apple Silicon or Intel; cross-architecture and Rosetta builds are not supported.
|
|
|
|
The resulting `.build/terebi.app` is self-contained: copy the whole app to a compatible Mac of the same architecture. No separate FFmpeg, Python, or yt-dlp installation is needed to run it.
|
|
|
|
### Install
|
|
|
|
```sh
|
|
make install # builds a release and installs under ~/.local
|
|
export PATH="$HOME/.local/bin:$PATH"
|
|
terebi --help
|
|
```
|
|
|
|
Use `make install PREFIX="/custom/path"` to change the prefix, or `make release` for just `.build/release/terebi.app`. Installation places the app in `lib/terebi/terebi.app` and its CLI symlink in `bin/terebi`. Quit running players before updating.
|
|
|
|
Builds are ad-hoc signed for personal use, not notarized. Bundled licenses and source archives are in the app's Resources; public binary redistribution requires a separate dependency/license audit, including the GPLv3+ standalone yt-dlp bundle.
|
|
|
|
## Usage
|
|
|
|
Open a file with **⌘O**, drag it onto the window, or use Finder's **Open With**. Open YouTube with **⇧⌘O** or drop a video link. Media starts automatically and resumes its saved position; finished videos restart from the beginning. Live and audio-only media do not save progress.
|
|
|
|
| Action | Default shortcut |
|
|
| --- | --- |
|
|
| Play / pause | Space or K |
|
|
| Seek backward / forward 5 seconds | ← / → |
|
|
| Seek backward / forward 10 seconds | J / L |
|
|
| Step one frame backward / forward (pauses playback) | , / . |
|
|
| Volume down / up | ↓ / ↑ |
|
|
| Mute / unmute | M |
|
|
| Fullscreen | F or ⌃⌘F; Esc to leave |
|
|
| Compact mode | P or ⌃⌘P |
|
|
| Always on top | ⇧P |
|
|
| Close media | ⇧⌘W |
|
|
| Quit | Q or ⌘Q |
|
|
|
|
Compact mode keeps playback in the same floating window; drag to move it and double-click to restore. The titlebar pin keeps the normal window on top. macOS media keys also control playback; previous/next seek five seconds rather than changing tracks.
|
|
|
|
### YouTube
|
|
|
|
Playback defaults to the best available SDR resolution up to **1080p**. Use **gear → Quality** to select another available resolution, including 4K, or enable automatic quality (off by default). **Show Buffer Info** displays the retained network buffer.
|
|
|
|
Only individual videos are supported, not playlists or channels. Private, age-restricted, region-blocked, or sign-in-required videos may fail; browser cookies are not read. The extractor is bundled, so YouTube compatibility updates require rebuilding/reinstalling terebi, not updating an external yt-dlp.
|
|
|
|
### Chromecast
|
|
|
|
Open media, select the **Cast** icon or **Playback → Cast to Device → Find Cast Devices…**, and choose a receiver on the same LAN. Allow macOS Local Network access and incoming firewall connections. Keep the Mac awake and connected: it relays the media to the receiver.
|
|
|
|
Existing controls operate remote playback. **Play on This Mac** returns to local playback at the receiver's position. Opening different media ends casting. Frame stepping and YouTube quality changes are local-only; live Cast playback is not seekable. Cast output is limited to 1080p/30 fps. The screen-and-triangle icon does not provide AirPlay support.
|
|
|
|
Cast trusts the selected LAN endpoint's self-signed certificate; use it only on a trusted network. Receiver captions and perceived A/V synchronization still need physical-device verification.
|
|
|
|
## Command line
|
|
|
|
Before installation, use `.build/terebi` instead of `terebi`:
|
|
|
|
```sh
|
|
terebi "/path/to/video.mp4"
|
|
terebi 'https://youtu.be/jNQXAC9IVRw'
|
|
terebi --new-instance --url 'https://www.youtube.com/watch?v=jNQXAC9IVRw'
|
|
terebi --new-instance --no-config "/path/to/video.mp4"
|
|
terebi -- -video.mp4
|
|
terebi --help
|
|
```
|
|
|
|
The CLI opens one file or video, reusing the running player by default. With no arguments it opens or activates the player without replacing media. Put `--new-instance` and `--no-config` before media arguments. Launch success means macOS accepted the request, not that playback succeeded; playback errors appear in the window.
|
|
|
|
### Resolved sources and progress reporting
|
|
|
|
Miruro playback requires a freshly resolved source document from an external caller such as Tubular; terebi does not discover episodes or accept Miruro page URLs directly.
|
|
|
|
```sh
|
|
terebi --new-instance --source-file '/private/session/source.json' \
|
|
--progress-file '/private/session/progress.jsonl'
|
|
```
|
|
|
|
Both options require `--new-instance`; `--progress-file` also works with YouTube. Use a private session directory and a nonexistent report destination. Keep the source file present and unchanged during playback; the caller owns cleanup. Reports contain playback facts, not watched-state decisions.
|
|
|
|
See the [integration contract](docs/miruro-playback-handoff.md) for source JSON, resource-header/origin restrictions, and progress schemas. Tubular still needs to adopt Miruro's version-2 progress identity.
|
|
|
|
## Configuration
|
|
|
|
The optional config is `$XDG_CONFIG_HOME/terebi/config.toml` when `XDG_CONFIG_HOME` is absolute, otherwise `~/.config/terebi/config.toml`. Omitted settings use defaults. To print all supported settings and key actions:
|
|
|
|
```sh
|
|
terebi --default-config
|
|
```
|
|
|
|
Example partial configuration:
|
|
|
|
```toml
|
|
[playback]
|
|
automatic_quality = true
|
|
|
|
[ui]
|
|
buffer_info = true
|
|
compact_snap_to_edges = true
|
|
compact_title_progress = "percentage" # "time", "percentage", or "none"
|
|
|
|
[keys]
|
|
play = "space"
|
|
pause = "space"
|
|
quit = "cmd+q"
|
|
quality_2160p = "ctrl+4"
|
|
```
|
|
|
|
Shortcut strings or arrays replace an action's defaults; `[]` unbinds it. Modifiers use `cmd`, `ctrl`, `alt`/`option`, and `shift`, joined with `+`. A chord may be shared by inverse actions such as play/pause, but not unrelated actions. Invalid settings and conflicting shortcuts are errors.
|
|
|
|
Settings load once at startup. Menu changes are session-only and never write the file; start a fresh player to apply edits. `--no-config` uses built-in settings on a fresh launch, not in an already-running player, and does not clear saved progress.
|
|
|
|
## Limits
|
|
|
|
- SDR output only; PQ/HLG HDR is rejected. No playlists, embedded/YouTube captions, manual audio-track selection, rotation, or deinterlacing. External resolved-source WebVTT subtitles are supported.
|
|
- H.264, HEVC, and VP9 prefer VideoToolbox decoding with software fallback; other codecs, including AV1, use software. Backward frame stepping can be slow on long-GOP or unindexed media.
|
|
- Network buffering is bounded and memory-only; live/non-seekable sources disable seeking and frame stepping. Expired stream URLs are not automatically refreshed.
|
|
- Audio-device changes during playback are not handled.
|
|
|
|
## Development checks
|
|
|
|
```sh
|
|
brew install ffmpeg # fixture generation only; not required to build or run terebi
|
|
make check
|
|
```
|
|
|
|
The full suite requires a graphical macOS session and a working audio device; it launches isolated app instances and plays short test audio. Targeted `check-*` targets are listed in the [Makefile](Makefile). Visual appearance, physical media-key routing, and receiver behavior still need manual checks.
|
|
|
|
`make benchmark-playback` measures cold source startup, cached/uncached seeks, and sustained native/Cast playback with repeatable loopback fixtures. It requires the same macOS session/audio device and fixture-generation FFmpeg; results exclude live extraction, WAN/TLS, and physical-receiver latency.
|
|
|
|
Playback terminology: [CONTEXT.md](CONTEXT.md).
|