定制 sugarcraft/sugar-reel 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

sugarcraft/sugar-reel

Composer 安装命令:

composer require sugarcraft/sugar-reel

包简介

Terminal video player for SugarCraft — plays mp4 (and more) by decoding frames on the fly and rendering them to ASCII / ANSI / truecolor half-block / sixel / kitty output.

README 文档

README

CI codecov Packagist Version License PHP

Terminal video player — plays mp4 / gif / avi / webm and more on the fly, rendering each frame as ASCII, ANSI 256-color, truecolor half-blocks, or via modern graphics protocols (sixel / kitty / iTerm2). Like mpv -vo tct, but in PHP and reusing the SugarCraft rendering stack throughout.

composer require sugarcraft/sugar-reel
use SugarCraft\Reel\Player;

// Play a video with auto-detected terminal capability.
$player = Player::open('clip.mp4', cols: 80, rows: 24);

// Run it (Space=play, q=quit).
(new \SugarCraft\Core\Program($player))->run();

Status: Step 7 ✓ — full implementation with ffmpeg decode pipe, pure-PHP GIF fallback, all rendering modes (ascii/ansi256/truecolor/ half-block/sixel/kitty/iTerm2), delta repaint, seek, speed control, and a runnable example.

Install

composer require sugarcraft/sugar-reel

Requires:

  • PHP 8.3+
  • ffmpeg and ffprobe in $PATH for mp4/avi/webm playback
  • ext-gd for .gif playback (pure-PHP fallback, no ffmpeg needed)
  • A terminal with at least 256-color support for ANSI modes

Usage

# Built-in synthetic test pattern (no video file needed)
php examples/play.php

# Play a real video file
php examples/play.php video.mp4

# Force a specific rendering mode
php examples/play.php video.mp4 halfblock
php examples/play.php video.mp4 ascii

# Force auto mode (probe terminal, pick best available)
php examples/play.php video.mp4 auto

# Set terminal dimensions
SUGAR_REEL_COLS=120 SUGAR_REEL_ROWS=40 php examples/play.php

Rendering modes

Mode Description Terminal requirement
ascii Grayscale luminance ramp ( .,:;i1tfLCG08@) Any
ansi256 256-color cube + grey ramp 256-color
truecolor 24-bit RGB truecolor 24-bit color
halfblock 24-bit half-blocks, 2× vertical resolution 24-bit color
sixel Sixel graphics protocol (DEC) Sixel-capable
kitty Kitty graphics protocol (DCS APC) Kitty-compatible
iterm2 iTerm2 inline image (OSC 1337) iTerm2 / WezTerm
auto Probe terminal, pick best available (default)

Auto mode probes the terminal using Mosaic::diagnose() (for sixel/kitty/ iTerm2) and falls back to ColorProfile::detect() for ANSI modes.

Luminance ramp selection

ASCII/ANSI256 text modes use a luminance ramp to map pixel brightness to characters. Three named ramps are available:

Ramp Characters Best for
minimal .:-=+*#%@ Low-resolution / high contrast
standard .,:;i1tfLCG08@ General use (default)
dense `` .`^",:;Il!i><~+_-?][}{1)( \/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$``
// Use the dense ramp for more detailed ASCII output
Reel::open('video.mp4')->withRamp('dense')->play();

Keyboard controls

Key Action
Space Pause / resume
Seek backward 10 frames
Seek forward 10 frames
[ Decrease playback speed (−0.25×, min 0.25×)
] Increase playback speed (+0.25×, max 4.0×)
09 Seek to 0–90% of video duration
m Cycle to next rendering mode
q / Esc Quit
resize Terminal resize (SIGWINCH) re-scales video automatically
loop Loop is set at open time via Reel::new()->withLoop(true)->play() (no keyboard shortcut)

Architecture

video file (mp4/gif/avi/webm)
        │
        ▼
┌───────────────────┐     ┌─────────────────┐
│ VideoSource::probe│     │ DecoderFactory  │
│   (ffprobe JSON)  │────▶│ create()        │
└───────────────────┘     └────────┬─────────┘
                                 │
                    ┌────────────┴────────────┐
                    │                        │
               GifDecoder             FfmpegDecoder
               (pure PHP / GD)         (ffmpeg pipe)
                    │                        │
                    └────────────┬───────────┘
                                ▼
                    ┌──────────────────────┐
                    │   RgbFrame (rgb24)    │
                    └──────────┬─────────────┘
                               │
                    ┌─────────┴──────────────┐
                    │   FrameRenderer /       │
                    │   Mosaic bridge         │
                    └─────────┬──────────────┘
                              │
                    ┌─────────┴──────────────┐
                    │   Player (TEA Model)    │
                    │   tick() → view()       │
                    └─────────┬──────────────┘
                              │
                    ┌─────────▼──────────────┐
                    │   Program (candy-core)  │
                    │   raw mode + alt screen│
                    └────────────────────────┘
  • Decode: FfmpegDecoder shells out to ffmpeg for raw RGB frames (pre-scaled to cell dimensions). GifDecoder wraps candy-flip's pure-PHP GIF decoder.
  • Render: Delegates to candy-mosaic for sixel/kitty/iTerm2. Uses candy-palette for color mapping. Delta repaint via candy-buffer.
  • Pace: Cmd::tick() wall-clock alignment via Sync, no busy-waiting.
  • Audio: AudioPlayer shells out to ffplay or mpv --no-video as the audio master clock.

Prior art

SugarReel has no single upstream. Its decode → render → pace pipeline draws on three terminal-video projects, credited here:

The rendering stack is reused from the SugarCraft ecosystem rather than reinvented: candy-mosaic (image → cell renderers), candy-flip (downsampling / dithering), candy-palette (color mapping), and candy-core (TEA runtime + frame pacing).

Known limitations

  • Audio plays at 1.0× regardless of playback speed. Changing speed with [/] only affects video pacing. The audio companion (ffplay/mpv) always plays at normal speed. A/V will diverge noticeably when using speeds other than 1.0×.

  • Seeking repositions audio but not frame-exactly. A seek creates a new AudioPlayer at the correct offset, but the video frame timing and audio timing are only approximately synchronized (frame-skip resync keeps them close at 1.0×).

  • GIF playback fills the terminal in HalfBlock mode (each cell = 2 source rows). In text modes (ascii/ansi256/truecolor) the GIF renders at its native pixel dimensions without 2× vertical scaling.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-22