Bad Apple

cont. (发现)在 Emacs 里运行毁灭战士

在Emacs里面播放Bad Apple?

我发现了这个9年前的项目 by y-usuzumi,它的原理是合成了一段ascii动画,在Emacs buffer里面刷新播放。

在考虑用Emacs玩doom(但不是走webkit支持)的时候,我一开始考虑的是把任意的X窗口同步刷到Emacs里面,我们不能没有对应的X窗口,不然程序无法运行。X支持窗口转发,因此我们可以捕捉窗口在任意时间的画面(有一个命令import可以做这件事)。

剩下的问题就是怎么在Emacs里面展示窗口的状态。我有两个点子:

  1. 我知道一个非常棒的项目chafa,它可以把图片转换成多种字符画格式,而Emacs有一个高性能的内置终端的扩展vterm。这种方式的结果我已经在之前的帖子里展示过了,如果直接在终端里使用这种方式展示的话效果会更好,特别是当你的终端支持sixel的时候,看起来和真正的X窗口转发别无二致。
window="DOOM"

while true; do
 xwd -name $window -silent |
 magick xwd:- png:- |
 chafa - 
 sleep 0.05
done

这个方式得到的动画帧率还可以,窗口输入有延迟,但是没有明显卡顿。关于为什么我觉得这不算在Emacs里玩doom:

  1. 因为Emacs支持显示图片,所以如果我们能够用一定的频率刷新图片,理论上就可以在Emacs里面实现定格动画的效果。那么Emacs最高支持多高的刷新频率呢?我在arm小板上实验的结果是:每秒2-3帧(参考以下给出的最小实现)。也许有更高效的实现?
input=/somewhere/badapple.mp4
output=/tmp/video.png
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $input)
interval=0.1

for t in $(seq 0 $interval $duration); do
  ffmpeg -v quiet -i $input -ss $t -frames:v -y $output
done
(let* ((buf (get-buffer-create "*Bad Apple*"))
       (img-file "/tmp/video.png"))
  (with-current-buffer buf
    (insert-image (create-image img-file))
    (run-with-timer 0.5 1
      (lambda () (clear-image-cache img-file))))
  (switch-to-buffer buf))
2 个赞

这相当于你在 Emacs 里用串流的方式玩 Doom

要看到画面只有两种方式,一种是串流,一种是原生渲染。

Emacs并不能直接提供doom所需要的图形渲染功能(webkit窗口的能力是由额外的webkit库提供的,实质上是浏览器里玩doom),所以只能是串流。

不过我一直想搞的emacs定格动画这里倒是有了点结论。下一步,如果我们要考虑在Emacs里面做动画渲染,那还是先搞个cairo画板比较好。然而cairo因为接口不向前兼容的问题一直在被喷,也许可以考虑把gles接口插进去。

Po Lu的内建webkit看起来是一个万金油方案,但是我对web不熟,而且认为这样子并不利于我用Elisp制作新玩具。我设计了一个类似swig的elisp ffi自动生成工具(目前还在原型阶段),有了这个应该可以快速把大部分linux底层库自动变成elisp模块(但我更倾向做完整的elisp cffi接口)。这个主意是上次用emacs弹吉他的时候去port了alsa pcm midi module产生的。

3 个赞

也许可以往 Emacs 里面嵌入一个 OpenGL 的 xwidget: GLArea (以及也有 emacs-gl).

(可惜用的是 mac 没法测试

1 个赞