一个 StepCode 扩展:在 TUI 右侧内嵌一个 FLV 播放器面板。看视频的同时可以继续和 agent 对话——按 esc 把键盘交还给编辑器,面板保持可见、视频继续播放(画中画),随时用 ctrl+alt+p 收回控制权。
╭─ demo.flv ────────────────────────────────╮
│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀│ ← 视频(half-block 真彩色)
│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀│
├───────────────────────────────────────────┤
│▶ 00:12/01:30 ████████░░░░░░░░░░ 12fps │ ← 状态 / 进度条
│space 播放暂停 · ←→ ±5s · ⇧←→ ±30s · m 音频 │ ← 按键提示
╰───────────────────────────────────────────╯
终端不能直接播视频,所以插件做了一条完整流水线(零 npm 依赖):
- ffprobe 读取宽高 / 帧率 / 时长;
- ffmpeg 把视频解码成 raw RGB 帧,通过管道流式输出(
-ss支持跳转,scale+fps直接输出面板尺寸); - Node 侧按帧切分,渲染成 half-block(
▀)24 位 ANSI 真彩色字符画——每个字符单元格显示 2 个垂直像素(前景色 = 上像素,背景色 = 下像素),任意支持真彩色的终端都能显示(Windows Terminal、iTerm2、Kitty、Ghostty、WezTerm…); - 面板是 TUI overlay(
anchor: right-center),通过OverlayHandle.unfocus()/focus()实现"内嵌且可继续对话"。
需要 ffmpeg(含 ffprobe;ffplay 可选,用于声音):
| 平台 | 安装 |
|---|---|
| Windows | winget install Gyan.FFmpeg |
| macOS | brew install ffmpeg |
| Linux | sudo apt install ffmpeg |
按 PATH → 常见安装目录(WinGet Links、C:\ffmpeg\bin、scoop、chocolatey、homebrew…)顺序查找,找不到时面板会给出安装提示。也可以用 --ffmpeg / 环境变量显式指定。
方式一:直接复制(推荐)
mkdir -p ~/.stepcode/agent/extensions/flv-player
cp index.ts ~/.stepcode/agent/extensions/flv-player/然后在 StepCode 里执行 /reload(或重启 step)。
方式二:开发期试用
step -ne -e ./index.ts
-ne(禁用扩展自动发现)是必须的:如果全局目录里已装有同名插件,-e显式加载会和自动发现的副本冲突(工具名重复,宿主拒绝启动)。 方式三:作为项目级插件:复制到仓库的.stepcode/extensions/flv-player/index.ts(项目被信任后生效)。
/flv movie.flv # 打开右侧播放面板(自动播放)
/flv movie.flv --width 40% # 面板宽度(默认 32%,也可写绝对列数如 48)
/flv movie.flv --fps 15 # 播放帧率(默认 12,不超过源帧率)
/flv movie.flv --no-audio # 静音
/flv movie.flv --external # 不用面板,直接用系统播放器打开
/flv movie.flv --ffmpeg "C:\ffmpeg\bin\ffmpeg.exe" # 指定 ffmpeg
/flv stop | focus | show | hide | status
LLM 也可以直接调用 flv_player 工具({ "path": "movie.flv" })帮用户放视频。
除了本地文件,也支持网络流——任何 ffmpeg 能打开的协议:
/flv http://host:8080/live/stream.flv # HTTP-FLV(最常见)
/flv rtmp://host/app/key # RTMP 推流/直播
/flv https://host/live/index.m3u8 # HLS
/flv rtsp://host:554/live # RTSP
/flv srt://host:9000 # SRT
行为差异(自动判定,无需开关):
| 本地文件 / 网络点播 | 直播流(URL 且时长未知) | |
|---|---|---|
| 状态栏 | ▶ 00:12/01:30 + 进度条 |
▶ LIVE 00:12,无进度条 |
| 快进/快退 | 支持(±5s / ±30s) | 不支持(提示“直播流不支持跳转”) |
| 结束 | 播完显示 ⏹ ended |
永不停播 |
| 画面比例 | 按探测比例 | 默认 16:9 网格 + letterbox 黑边,任何比例都不变形 |
说明:
- 探测无限直播流时 ffprobe 会阻塞,因此 URL 探测带 2.5 秒 socket 超时;超时则回退到默认网格直接开播(这就是直播地址打开略慢几秒的原因)。
- 断流不自动重连:ffmpeg 退出后面板显示错误信息,重新执行
/flv <url>即可。 - 直播默认尝试用 ffplay 放声音(
--no-audio或m可静音)。
| 键 | 作用 |
|---|---|
space |
播放 / 暂停 |
← → |
快退 / 快进 5 秒 |
shift+← shift+→ |
±30 秒 |
enter |
播完后重播 |
m |
开 / 关声音(ffplay) |
q / ctrl+c |
关闭面板 |
esc |
脱离:面板保持可见、继续播放,键盘还给编辑器 |
脱离后按 ctrl+alt+p 或 /flv focus 重新取得控制权;/flv hide / /flv show 可临时收起面板。
| 变量 | 作用 |
|---|---|
FLV_PLAYER_FFMPEG / FLV_PLAYER_FFPROBE / FLV_PLAYER_FFPLAY |
覆盖可执行文件(支持 node "script.mjs" 这类带参数的命令) |
FLV_PLAYER_OPENER |
非 TUI 模式的系统打开命令模板,{file} 会被替换(默认 cmd /c start "" {file} / open {file} / xdg-open {file}) |
- 终端 < 96 列时面板自动隐藏(
visible回调),避免遮挡编辑区。 - 暂停 / 跳转会重启解码器:seek 用
-ss从头截取,管道不堆积;跳转后若处于暂停态,会先拉一帧预览。 - 音频是 best-effort:ffplay 独立进程播放,暂停 / 跳转 / 关闭会同步停掉;与画面可能有轻微漂移,
m可静音。没有 ffplay 时自动静音。 - 解码器最多领先播放 3 秒(stdout 流控),长视频不会撑爆内存。
- 不只是 FLV:任何 ffmpeg 能解码的容器(mp4、mkv、mov…)都能放,命令叫
/flv只是沿用需求叫法。 - overlay 是浮层,不改变主界面布局(真正的侧栏 reflow TUI 不支持)。
npm test # 32 个测试:fake-ffmpeg 全流程 + 真实 ffmpeg 端到端(无 ffmpeg 自动跳过)
npm run typecheckindex.ts— 插件本体(可擦除 TypeScript,Node ≥ 22.19 直接可跑)test/harness.mjs— mockctx/tui,驱动真实组件test/fake-ffmpeg.mjs— ffmpeg/ffprobe/ffplay 测试替身,按scale/fps吐确定性图案帧test/player.test.mjs— 单元 + 全流程(解码、渲染、按键、暂停、seek、EOF、错误路径、resize)test/real-ffmpeg.test.mjs— 用真实 ffmpeg + 真实 FLV(自动生成 4 秒 testsrc2 样本)做端到端验证test/step-load-probe.ts— 验证插件能被 StepCode 真实 jiti 加载器加载:step -e test/step-load-probe.ts -p "hi"step-harness.d.ts— 本地类型声明(@step-harness/*不发布到 npm,仅供仓库独立 typecheck)