2 个版本
0.1.1 | 2020 年 6 月 12 日 |
---|---|
0.1.0 | 2020 年 6 月 8 日 |
#130 在 渲染
78KB
2K SLoC
Xfbs 播放器
想法是写一个工具,我可以用来创建关于编程的视频。它应该能够接受一个脚本(定义所有场景,包括动画、文本、代码输入、终端会话回放、背景音频、前景音频(旁白),每个场景或时间偏移等。
- 文本
- 动画
- 代码输入
- 终端会话回放
- 背景音频
- 前景音频(旁白),每个场景或时间偏移
这应该可以在 Gtk 播放器应用程序中回放以供审查,或者进一步处理成视频文件(任何所需格式)。还应支持 CLI,并加载预先解析的序列化数据结构。
基础应该围绕一个包含音频(带有时间索引)以及动画(带有类型、参数、Z 值和时间索引)的数据结构。然后播放器将遍历此数据结构,并生成它看到的东西。
数据结构必须能够支持分数时间,以便可以将帧率设置为所需的任何值(24、30、60、最大帧率)。
脚本语言(REPL)
- https://github.com/jonathandturner/rhai
- https://github.com/PistonDevelopers/dyon
- JSON?
- https://github.com/gluon-lang/gluon
声音?
- 可能需要支持 AAC 和 Vorbis(用于 mp4 和 webm)
- 需要一些库可以处理任意声音的解码、混合以及重新编码回某种格式。
视频生成?
- 某种类型的 h.264 编码器以及 webm?
动画?
- cairo 和 gtk,结合在一起
二进制格式?
- 能够运行脚本,创建所有数据结构,然后使用 serde 将其序列化到某种可以共享的格式中。
语法高亮器?
- ???
功能
- 重点:ffmpeg 编码
- 重点:ttyrec 播放
- 重点:LaTeX 支持?
- 重点:文本输入
- 重点:淡入淡出
- 将一切从 box 迁移到 rc(尽管它在序列化期间没有帮助)
- 完成音频实现
- 完成动画实现
- 使用 HSLuv 或类似的东西进行背景颜色渐变?
- 加载并显示图像
- 实现包装类型
- 实现斜体等
- 实现自定义颜色方案
- TEX 显示(通过 svg 渲染?)
- 使用 mathjax 和 quick-js 的简单数学显示?
- 音频编码
- 屏幕上显示位置
- 延迟 png 渲染
- 渲染为JPEG
- 渲染为APNG
- 渲染为webm
- 渲染为mp4
- 实现其他缓动函数
- 淡入
- 可渲染项目组
- CI测试
- 为可绘制对象编写单元测试
- 为动画对象编写单元测试
- 自定义缓动函数
- 实现场景
- 使用resvg显示SVG
- 渲染为GIF
- 移动正弦波(?)
- 移动三次方
- 移动二次方
- 实现音频架构
- 使高亮延迟加载
- 使高亮返回错误
- 修复解析速度慢的问题
- 使颜色方案延迟加载
- 音频解码
- mp3解码
- wav解码
- ogg解码
- 使用rodio播放音频
- 实时播放控制
- 暂停、恢复
- 动画
- 线性移动
- 平滑移动
- 使彩色文本可缩放
- 使用crate显示源代码(高亮)
- 实现新架构
- 脚本语言接口
- 文本显示
- 彩色文本显示
- 渲染为PNG
- 实时播放
- 设置背景颜色
- 为特质提出新架构
用法
您将“电影”作为rhai脚本编写。它看起来像这样
let movie = movie();
let bg = background(...);
movie
您可以使用编译子命令将此脚本编译成电影(使用自定义二进制格式)。
$ xfpl compile script.rhai -o movie.xfpl
这会生成一个.xfpl
二进制文件,您可以使用播放子命令来播放它。
$ xfpl play movie.xfpl
为了方便,可以省略编译脚本,并使用--parse
标志告诉播放器自行解析脚本。
$ xfpl play --parse script.rhai
最后,可以使用render
子命令将电影导出为视频文件。
$ xfpl render script.rhai --format apkg --output out.png --resolution fullhd
请注意,这可能需要一些时间,通常使用播放器观看会更好。
我想实现自己的自定义绘图函数
您需要决定您是要绘制静态内容还是动画内容。如果您想绘制静态内容(即,不改变的内容),您需要实现Drawable
特质。例如
struct MyDrawing;
impl MyDrawing {
pub fn new() -> MyDrawing {
MyDrawing
}
}
#[typetag::serde]
impl Drawing for MyDrawing {
pub fn draw(&self, context: cairo::Context) {
// draw
context.set_source.rgba(1.0, 0.0, 1.0, 0.5);
context.move_to(0.1, 0.1);
context.draw();
}
pub fn size(&self) -> Size {
Size::new(0.1, 0.1)
}
}
在draw()
函数中,您可以基本上调用任何Cairo绘图函数。如果您将要调用会改变上下文的内容,您应该在保存/恢复块中包装您的绘图代码,如下所示
context.save();
// your code here
context.restore();
否则可能会破坏某些东西。size()
函数应返回您所绘制的任何内容的大小。
如果您注意到您实际上想要绘制的是动画内容,那么您需要实现的是Animated特质。这与Drawable特质类似,但在绘制时,它会获取当前的时间戳,具有持续时间,并且可以播放音频文件。
依赖项
~30–41MB
~722K SLoC