Asciinema-Player是一款著名的的终端录制播放器,可用于播放asciinema录制的播放文件,经常被用来进行终端操作演示。这里也将其引入到了当前Hugo博客中使用,下面我将讲讲引入的过程。
1.效果展示
Talk is cheap, show the result ~
2.需求分析
为什么需要在Hugo里面使用终端播放器Asciinema-Player呢?
作为技术人员,在写博客时总是需要进行一些终端操作演示,而演示方式无非以下几种:
方式 |
优点 |
缺点 |
视频 |
能配音配特效 |
网站流量消耗大,不能复制文本 |
动图 |
文件相对小些 |
不能控制进度,不能复制文本 |
代码 |
占用流量小,能复制 |
不能控制进度,也不太好展示效果 |
而终端录制播放器Asciinema-Player则兼容体积小、能控制、能复制于一体并能完美复现终端操作场景,非常适合用于在博客中进行一些终端操作演示。
3.解决方案
首先,在网上找下前人在Hugo博客里扩展嵌入asciinema-player的方法,比如 Embedding asciinema cast in your Hugo site。
shortcode
可以找到里面asciinema-player的shortcode代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<p>
<asciinema-player
src="/casts/{{ with .Get "key" }}{{ . }}{{ end }}.cast"
cols="{{ if .Get "cols" }}{{ .Get "cols" }}{{ else }}640{{ end }}"
rows="{{ if .Get "rows" }}{{ .Get "rows" }}{{ else }}10{{ end }}"
{{ if .Get "autoplay" }}autoplay="{{ .Get "autoplay" }}"{{ end }}
{{ if .Get "preload" }}preload="{{ .Get "preload" }}"{{ end }}
{{ if .Get "loop" }}loop="{{ .Get "loop" }}"{{ end }}
start-at="{{ if .Get "start-at" }}{{ .Get "start-at" }}{{ else }}0{{ end }}"
speed="{{ if .Get "speed" }}{{ .Get "speed" }}{{ else }}1{{ end }}"
{{ if .Get "idle-time-limit" }}idle-time-limit="{{ .Get "idle-time-limit" }}"{{ end }}
{{ if .Get "poster" }}poster="{{ .Get "poster" }}"{{ end }}
{{ if .Get "font-size" }}font-size="{{ .Get "font-size" }}"{{ end }}
{{ if .Get "theme" }}theme="{{ .Get "theme" }}"{{ end }}
{{ if .Get "title" }}title="{{ .Get "title" }}"{{ end }}
{{ if .Get "author" }}author="{{ .Get "author" }}"{{ end }}
{{ if .Get "author-url" }}author-url="{{ .Get "author-url" }}"{{ end }}
{{ if .Get "author-img-url" }}author-img-url="{{ .Get "author-img-url" }}"{{ end }}
></asciinema-player>
</p>
|
细细口味了下这段代码,结合自己需求进行了修改:
Talk is cheap, show me the code ~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# themes/iLoveIt/layouts/shortcodes/asciinema.html
<p>
<asciinema-player
{{- with .Get "src" }} src="{{ . }}" {{ end -}}
{{- with .Get "key" }} src="/casts/{{ . }}.cast"{{ end -}}
cols="{{ if .Get "cols" }}{{ .Get "cols" }}{{ else }}640{{ end }}"
rows="{{ if .Get "rows" }}{{ .Get "rows" }}{{ else }}10{{ end }}"
{{- with .Get "autoplay" }}autoplay="{{ . }}"{{ end -}}
{{- with .Get "preload" }}preload="{{ . }}"{{ end -}}
{{- with .Get "loop" }}loop="{{ . }}"{{ end -}}
start-at="{{ if .Get "start-at" }}{{ .Get "start-at" }}{{ else }}0{{ end }}"
speed="{{ if .Get "speed" }}{{ .Get "speed" }}{{ else }}1{{ end }}"
{{- with .Get "idle-time-limit" }}idle-time-limit="{{ . }}"{{ end -}}
{{- with .Get "poster" }} poster="{{ . | safeURL }}"{{ end -}}
{{- with .Get "font-size" }}font-size="{{ . }}"{{ end -}}
{{- with .Get "theme" }}theme="{{ . }}"{{ end -}}
{{- with .Get "title" }}title="{{ . }}"{{ end -}}
{{- with .Get "author" }}author="{{ . }}"{{ end -}}
{{- with .Get "author-url" }}author-url="{{ . }}"{{ end }}
{{- with .Get "author-img-url" }}author-img-url="{{ . }}"{{ end -}}
fit="{{ if .Get "fit" }}{{ .Get "fit" }}{{ else }}width{{ end }}"
></asciinema-player>
{{- .Page.Scratch.SetInMap "this" "asciinema" true -}}
</p>
|
注意看高亮部分,主要修改了以下几点:
修改点
if .Get
形式代码过于累赘,这里把不需要取默认值的语句统统改成了with .Get
形式;
- 只有固定的
key
方法从本站获取.cast
录制文件,这里扩展了src
以便从站外获取录制文件地址;
poster
这里会得到一个奇怪的数据#ZgotmplZ
,它是一个安全防护的默认数据,见官方说明,会导致设置指定时间封面无效,解决起来也简单,加上| safeURL
管道方法就可解决;
js、css
参考方案里动态引入js
和css
,用到的该播放器的文章里需设置asciinema
为true
:
1
2
3
|
{{ if .Params.asciinema }}
<script src="{{ .Site.BaseURL }}js/asciinema-player.js"></script>
{{ end }}
|
1
2
3
4
5
6
7
8
|
---
title: Kubernetes Backup - ARK
description: Kubernetes backup process using ark
asciinema: true
tags:
- kubernetes
- backup
---
|
可以看到上面是通过在文章里加asciinema
参数实现的js
、css
资源动态加载,其实可以参考其它如mermaid
的接入方式,直接在渲染时置标记就好:
122
123
124
125
126
127
128
129
|
# themes/iLoveIt/layouts/partials/assets.html
{{- /* asciinema */ -}}
{{- if (.Scratch.Get "this").asciinema | or $params.draft -}}
{{- $source := "lib/asciinema/asciinema-player.min.css" -}}
{{- dict "Source" $source "Fingerprint" $fingerprint | dict "Scratch" .Scratch "Data" | partial "scratch/style.html" -}}
{{- $source := "lib/asciinema/asciinema-player.min.js" -}}
{{- dict "Source" $source "Fingerprint" $fingerprint | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- end -}}
|
其中$params.draft
是为了开发模式下也能设置草稿参数进行预览:
53
54
55
56
57
58
59
60
|
# themes/iLoveIt/assets/data/cdn/jsdelivr.yml
gitalkJS: gitalk@1.7.2/dist/gitalk.min.js
# valine@1.5.0 https://valine.js.org/
valineJS: valine@1.5.0/dist/Valine.min.js
asciinemaJS: asciinema-player@3.0.1/dist/index.min.js
# cookieconsent@3.1.1 https://github.com/osano/cookieconsent
cookieconsentCSS: cookieconsent@3.1.1/build/cookieconsent.min.css
cookieconsentJS: cookieconsent@3.1.1/build/cookieconsent.min.js
|
调整下css
样式,让播放器能够在超出显示区域时滚动过去:
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
/* themes/iLoveIt/assets/lib/asciinema/asciinema-player.min.css */
.asciinema-terminal {
box-sizing: content-box;
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box;
padding: 0px;
margin: 0px;
display: block;
white-space: pre;
word-wrap: normal;
word-break: normal;
border-radius: 5px;
border-style: solid;
cursor: pointer;
border-width: 0.3em;
font-family: Consolas, Menlo, 'Bitstream Vera Sans Mono', monospace, 'Powerline Symbols', 'Terminal Glyphs';
line-height: 1.3333333333em;
width: auto;
max-width: 100%;
overflow-x: auto;
overflow-y: hidden;
}
.asciinema-terminal .line {
letter-spacing: normal;
overflow: hidden;
height: 1.3333333333em;
}
.asciinema-terminal .line span {
padding: 0;
display: inline-block;
height: 1.3333333333em;
}
.asciinema-terminal .line {
display: block;
width: 4000px;
}
|
font
可以注意到font-family
额外加了Terminal Glyphs
,这也可参考了 Custom Fonts in Asciinema。
主要是为了不至于出现下文中乱码的问题。正常如下:
4.使用方法
asciinema-player
asciinema-player即播放器,在博客中使用只需简单在文章中加入以下代码:
其中,cols
、rows
分别为行列,preload
则是要不要预加载,poster
则是封面,有data
模式也有npt
模式,npt
即按时间截取封面,上面的就是截取55
秒时的终端作为封面。
另外还有speed
:播放速度,autoplay
:自动播放等参数,具体可参考asciinema-player设置
呈现效果如下(借用了helix-editor的演示,文件大些可能加载慢些):
点击播放按钮播放,可拖动进度条或者使用方向键控制播放进度。
asciinema
上述终端播放所使用的cast
文件,都是使用asciinema在终端录制的。
安装
使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
➜ ~ asciinema --help
usage: asciinema [-h] [--version] {rec,play,cat,upload,auth} ...
Record and share your terminal sessions, the right way.
positional arguments:
{rec,play,cat,upload,auth}
rec Record terminal session
play Replay terminal session
cat Print full output of terminal session
upload Upload locally saved terminal session to asciinema.org
auth Manage recordings on asciinema.org account
options:
-h, --help show this help message and exit
--version show program's version number and exit
example usage:
Record terminal and upload it to asciinema.org:
asciinema rec
Record terminal to local file:
asciinema rec demo.cast
Record terminal and upload it to asciinema.org, specifying title:
asciinema rec -t "My git tutorial"
Record terminal to local file, limiting idle time to max 2.5 sec:
asciinema rec -i 2.5 demo.cast
Replay terminal recording from local file:
asciinema play demo.cast
Replay terminal recording hosted on asciinema.org:
asciinema play https://asciinema.org/a/difqlgx86ym6emrmd8u62yqu8
Print full output of recorded session:
asciinema cat demo.cast
For help on a specific command run:
asciinema <command> -h
|
另外如果想将其转化为gif动图,也可以使用asciicast2gif。
5.总结
通过以上实践,虽然过程有些曲折,但最终还是顺利地将asciinema-player终端播放器引入到了hugo中使用,后续发布的博客也将经常见到其身影。