p

presio

@preview

Attach speaker notes and embedded media to PDF slides for presio.xyz

v0.2.3
MIT

Package Information

Last Updated
Minimum Typst Version
0.15.0
Categories
visualization

1. Get the package

Download the package using the TPIX CLI:

tpix get @preview/presio:0.2.3

2. Import in your Typst file

Add this to your .typ file:

#import "@preview/presio:0.2.3": *

Version History

0.2.30.15.0
f3f9a0b912f7...
0.2.20.15.0
16ca364d18dd...
0.2.10.15.0
d64d85dfd020...
0.2.00.15.0
66b7f5b6c89d...
0.1.00.13.0
e0ee22f7e413...

presio

Attach speaker notes and embedded media (GIF / MP4 / WebM) to PDF slides
so they can be presented with the presio.xyz viewer.

presio is framework-agnostic — it works with polylux,
touying, or plain Typst pages. It
only contributes two functions; layout and slide flow are up to your existing
template.

Present the Touying demo
Present the polylux demo
Present the plain demo

Install

#import "@preview/presio:0.2.3": media, speaker-notes

Requires Typst 0.15 or newer (for the file path type). Users on Typst
0.13–0.14 can pin to @preview/presio:0.1.0, which has a slightly more
verbose bytes-based API.

Usage

Speaker notes

= Introduction

Hello world.

#speaker-notes[
  Remember to mention the funding agency before the next slide.
]

A JSON sidecar notes-slide-<N>.json is attached to the PDF. Multiple
speaker-notes[…] calls on the same slide are concatenated into a single
attachment, in source order.

Embedded media (local file)

#media(path("figures/demo.gif"), width: 60%)

path("…") is Typst 0.15's file-path type — it resolves relative to the
file that constructed it, so the package can read() and image() the
target on the caller's behalf. The bytes are embedded in the PDF via
pdf.attach and a placement descriptor JSON is written alongside it.

By default the in-slide preview is image(source). For MP4 / WebM
(which Typst can't render directly) pass an explicit placeholder: image("poster.png"), or placeholder: none to get a dark block.

Embedded media (URL)

#media(
  "https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif",
  width: 40%,
  aspect-ratio: 1,
)

Nothing is attached to the PDF; the viewer fetches the URL at presentation time.

YouTube / Vimeo

URLs from YouTube (youtube.com/watch?v=…, youtu.be/…, youtube.com/embed/…,
youtube.com/shorts/…, youtube.com/live/…, youtube-nocookie.com/embed/…,
and any subdomain such as m.youtube.com) and Vimeo (vimeo.com/<id>,
vimeo.com/video/<id>, player.vimeo.com/video/<id>,
vimeo.com/channels/<channel>/<id>, vimeo.com/groups/<group>/videos/<id>)
are detected automatically and emitted with kind: "youtube" / kind: "vimeo" plus an extracted video_id
the viewer can use to build an iframe embed.

#media("https://www.youtube.com/watch?v=dQw4w9WgXcQ", width: 60%, aspect-ratio: 16/9)
#media("https://vimeo.com/76979871", width: 60%, aspect-ratio: 16/9)

media parameters

Parameter Default Notes
source Either a path (from path("…")) or a http(s):// URL string
name none Override for the attachment filename / MIME sniff. Auto-derived from the path's filename when omitted.
placeholder auto autoimage(source) for files, dark block for URLs. none → force dark block. Any content → use it.
width auto Length, ratio of the container width, or auto (natural width of placeholder, else container width)
height auto Length, ratio, or auto (derived from placeholder / aspect-ratio / 16:9)
aspect-ratio none Width/height ratio, e.g. 16/9
autoplay true Forwarded to the viewer
loop true Forwarded to the viewer

Supported media types

The MIME is sniffed from the extension of the source path's filename (file mode) or the URL (URL mode):

Extension MIME
.gif image/gif
.mp4 video/mp4
.webm video/webm

Sidecar JSON schemas

notes-slide-<N>.jsonnotes is always an array (one entry per
speaker-notes call on that slide, in source order):

{ "slide": "3", "notes": [ "<typst content>", "<typst content>" ] }

media-slide-<N>-<id>.json

Common fields: kind, slide, id, mime, x_pt, y_pt, w_pt, h_pt,
autoplay, loop. The remaining fields depend on kind:

kind Extra fields
file filename (PDF attachment name)
url url (direct media URL)
youtube url, video_id
vimeo url, video_id
{
  "kind": "file",
  "slide": 3,
  "id": "demo_gif",
  "mime": "image/gif",
  "x_pt": 72.0, "y_pt": 120.0, "w_pt": 432.0, "h_pt": 243.0,
  "autoplay": true,
  "loop": true,
  "filename": "media-demo_gif.gif"
}

Examples

A complete deck for each supported workflow lives under examples/. Each
folder is self-contained (its own demo.gif) and is compiled to PDF
alongside the source.

Framework Source Compiled PDF
Plain Typst examples/plain/example.typ example.pdf
polylux examples/polylux/example.typ example.pdf
touying examples/touying/example.typ example.pdf

Rebuild with typst compile --root . examples/<framework>/example.typ examples/<framework>/example.pdf from the repo root. The --root . flag is required so the file-path sandbox can resolve demo.gif.

License

MIT — see LICENSE.