我想知道是否可以玩asciinema.orgLaTeX Beamer 框架内的屏幕录像?
以下是屏幕录像的示例链接:https://asciinema.org/a/418574. 注意它的原始格式是.cast
。
提供的三种方法asciinema.org
:
- HTML:
<a href="https://asciinema.org/a/418574" target="_blank"><img src="https://asciinema.org/a/418574.svg" /></a>
- 降价:
[![asciicast](https://asciinema.org/a/418574.svg)](https://asciinema.org/a/418574)
- 嵌入播放器:
<script id="asciicast-418574" src="https://asciinema.org/a/418574.js" async></script>
答案1
更新:播放器选项
可以在beamer
课堂演示中以交互方式播放 asciinema.org 屏幕录像。
但是,asciinema.org 依赖 HTML5 标准,该标准不接受 PDF 作为输出格式。因此,我们需要求助于 SVG,它在 Chrome、Chromium、Edge 和 Firefox 等现代 Web 浏览器中运行良好。
下面的代码示例定义
\includeasciinema{<width>}{<height>}{<asciinema id number>}[<player options>]
它采用小部件尺寸和数字海胆属id,此处:418574
,作为强制参数。需要对大小参数进行一些调整,以使小部件适合幻灯片beamer
而不显示垂直滚动条。
第四个,选修的参数允许进一步调整玩家行为。在GitHub 页面,最有用的是:
autoplay=true
loop=true
startAt=<ss> | <mm>:<ss> | <hh>:<mm>:<ss>
speed=<number .gt. 0.0>
多个播放器选项必须用“&”符号(“ &
”)连接,即
loop=true&speed=0.5&startAt=5
请注意,在 GitHub 页面上, 的autoplay
拼写错误为autoPlay
,这不起作用。此外, 还startAt
暗含autoplay
。
幻灯片导航(PgUp、PgDn、Home、End、鼠标左键/右键单击、鼠标滚轮、光标自动隐藏)的代码取自另一篇帖子。
dvilualatex
SVG 输出由和生成dvisvgm
(假设输入文件example.tex
):
dvilualatex example
dvilualatex example
dvisvgm --zoom=-1 --font-format=woff2 --bbox=papersize --page=1- --linkmark=none example
然后,example-1.svg
在 Web 浏览器中打开。
实例 (点击开始演示,通过键盘或鼠标左键/右键单击导航,F11 为全屏):
完整代码loop
和speed
播放器选项设置:
\documentclass[dvisvgm,hypertex,aspectratio=169]{beamer}
\usefonttheme{serif}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% asciinema inclusion command
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \includeasciinema{<width>}{<height>}{<asciinema id number>}[<player options>]
%
% options example: autoplay=true&loop=true&speed=0.5
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ExplSyntaxOn
\NewDocumentCommand\includeasciinema{mmmO{}}{
\group_begin:
\str_set:Nx\l_ascma_optarg_str{#4}
\str_replace_all:Nnn\l_ascma_optarg_str{&}{&}
\leavevmode
\special{dvisvgm:bbox~\dim_eval:n{#1}~\dim_eval:n{#2}~0pt~transform}
\tl_set:Nx\l_ascma_viewbox_wd_tl{\fp_eval:n{
\g_ascma_px_per_bp_tl*\dim_to_decimal_in_bp:n{#1}}}
\tl_set:Nx\l_ascma_viewbox_ht_tl{
\fp_eval:n{\g_ascma_px_per_bp_tl*\dim_to_decimal_in_bp:n{#2}}}
\special{dvisvgm:raw
<g~transform='translate({?x},{?(y-(\dim_to_decimal_in_bp:n{#2}))})'>
<svg~
width='\dim_to_decimal_in_bp:n{#1}'~
height='\dim_to_decimal_in_bp:n{#2}'~
viewBox='0~0~\l_ascma_viewbox_wd_tl\space\l_ascma_viewbox_ht_tl'
>
<foreignObject~width='\l_ascma_viewbox_wd_tl'~height='\l_ascma_viewbox_ht_tl'>
<g~xmlns='http://www.w3.org/1999/xhtml'>
<iframe~
width='100\ascma_percent:'~height='100\ascma_percent:'~frameborder='0'~
allowfullscreen='true'~title='asciinema~player'~
src='https://asciinema.org/a/#3/iframe?\l_ascma_optarg_str'
/>
</g>
</foreignObject>
</svg>
</g>
}
\hbox_to_wd:nn{#1}{\vrule~width~\c_zero_dim~height~\dim_eval:n{#2}~depth~0pt\hss}
\group_end:
}
% assumed vert. screen resolution, for setting <svg> viewBox dimensions
\tl_const:Nn\g_ascma_screen_px_tl{1080} % Full HD
\tl_const:Nx\g_ascma_px_per_bp_tl{\fp_eval:n{\g_ascma_screen_px_tl/\dim_to_decimal_in_bp:n{\paperheight}}}
\group_begin:
\char_set_catcode_other:N\%
\cs_new_nopar:Nn\ascma_percent:{%}
\group_end:
\ExplSyntaxOff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% slide navigation via keyboard and mouse left-or-right-click/mouse wheel,
% mouse cursor autohide on idle; navigation symbols <--, -->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usepackage{fontawesome5}
\setbeamertemplate{navigation symbols}{}
\AddToHook{shipout/before}{\xdef\currentPageNumber{\inteval{\ReadonlyShipoutCounter+1}}}
\AddToHook{shipout/foreground}{%
\put(0,0){%
\raisebox{-\dimexpr\height+0.5ex\relax}[0pt][0pt]{\makebox[\paperwidth][r]{%
\normalsize\color{structure!40!}%
\ifnum\currentPageNumber>1%
\href{\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber-1\relax}.svg}{\faArrowLeft}%
\else%
\textcolor{lightgray}{\faArrowLeft}%
\fi\hspace{0.5ex}%
\ifnum\currentPageNumber<\PreviousTotalPages%
\href{\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber+1\relax}.svg}{\faArrowRight}%
\else%
\textcolor{lightgray}{\faArrowRight}%
\fi%
\hspace{0.5ex}%
}}%
}%
\special{dvisvgm:raw
<style>svg{cursor: none}</style>%
<defs>%
<script type="text/javascript">%
<![CDATA[%
var cursorTimer;%
var downOnLink=false;%
var downOnRoot=false;%
function islink(tg){return (tg.tagName=='a') ? true : tg.parentNode ? islink(tg.parentNode) : false;};%
function ismmedia(tg){return (tg.tagName=='video'||tg.tagName=='audio') ? true : tg.parentNode ? ismmedia(tg.parentNode) : false;};%
document.addEventListener('mousemove', function(e){%
if(islink(e.target)||ismmedia(e.target)||e.target.getAttribute('class')=='annot'){%
e.target.style.cursor='pointer';}else{e.target.style.cursor='default';}%
try{clearTimeout(cursorTimer);}catch(err){};%
cursorTimer=setTimeout(function(){e.target.style.cursor='none';},3000);%
});%
window.addEventListener('contextmenu', function(e){% capture right click
if(!islink(e.target)&&!ismmedia(e.target)) e.preventDefault();%
});%
document.addEventListener('mousedown', function(e){%
if(islink(e.target)||ismmedia(e.target)) downOnLink=true;%
else downOnRoot=true;%
});%
document.addEventListener('mouseup', function(e){%
if(downOnLink||!downOnRoot){downOnLink=false;return;}%
downOnRoot=false;%
\ifnum\currentPageNumber<\PreviousTotalPages
if(!e.shiftKey&&e.button==0) document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber+1\relax}.svg');%
\fi%
\ifnum\currentPageNumber>1
if(e.shiftKey||e.button>1) document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber-1\relax}.svg');%
\fi%
});%
document.addEventListener('wheel', function(e){%
\ifnum\currentPageNumber<\PreviousTotalPages
if(e.deltaY>0){%
document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber+1\relax}.svg');%
}%
\fi%
\ifnum\currentPageNumber>1
if(e.deltaY<0){%
document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber-1\relax}.svg');%
}%
\fi%
});%
document.addEventListener('keydown',function(e){%
\ifnum\currentPageNumber<\PreviousTotalPages
if(e.key=='PageDown'||e.key=='ArrowDown'||e.key=='ArrowRight')%
document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber+1\relax}.svg');%
\fi%
\ifnum\currentPageNumber>1
if(e.key=='PageUp'||e.key=='ArrowUp'||e.key=='ArrowLeft')%
document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{\the\numexpr\currentPageNumber-1\relax}.svg');%
\fi%
if(e.key=='Home')
document.location.replace('\jobname-\zeroPad{\PreviousTotalPages}{1}.svg');%
if(e.key=='End')
document.location.replace('\jobname-\PreviousTotalPages.svg');%
});%
]]>%
</script>%
</defs>%
}%
}%
% helper macro \zeroPad : zero-pads integer according to template,
% e. g. 123 --> 00123 if template is `99999`
% #1: arbitrary integer number as template specifying the
% width, e. g. `987654' for a width of 6 digits
% #2: the number to be formatted
\def\zeroPad#1#2{\zeroPadI{\zeroTemplate{0}{#1}}{#2}}
%low level macros used by \zeroPad
\def\zeroPadI#1#2{% #1: string of zeros specifying width, #2 number
\ifnum1#2<1#1
\zeroPadI{#1}{0#2}%
\else%
#2%
\fi%
}%
\def\zeroTemplate#1#2{% create template (string of zeros) from given num
\ifnum10#1>1#2
#1%
\else%
\zeroTemplate{0#1}{#2}%
\fi%
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\title{Embedding \emph{asciinema} screen recordings}
\subtitle{Use a Web browser and press \framebox{F11}}
\author{AlexG}
\date{\today}
\begin{document}
\frame{\titlepage}
\begin{frame}{Game of Life example}
\includeasciinema{0.4\textwidth}{0.48\textwidth}{418574}[loop=true&speed=0.5]
\end{frame}
\end{document}