# Media Directives URL: /bengal/docs/0.4.3/reference/directives/media/ Section: directives Tags: reference, directives, media, video, audio, embed, youtube, vimeo, tiktok, spotify, soundcloud, figure -------------------------------------------------------------------------------- Media Directives Media directives embed external content like videos, code playgrounds, and terminal recordings into your documentation. All embeds are privacy-respecting by default and meet WCAG 2.1 AA accessibility requirements. Quick Reference Directive Purpose Required Options {youtube} YouTube video :title: {vimeo} Vimeo video :title: {tiktok} TikTok video :title: {video} Self-hosted video :title: {spotify} Spotify track/album/playlist/podcast :title: {soundcloud} SoundCloud track/playlist :title: {figure} Image with caption :alt: {audio} Self-hosted audio :title: {gist} GitHub Gist — {codepen} CodePen embed :title: {codesandbox} CodeSandbox embed :title: {stackblitz} StackBlitz embed :title: {asciinema} Terminal recording :title: Video Embeds YouTube Embed YouTube videos with privacy-enhanced mode enabled by default (youtube-nocookie.com). Syntax: :::{youtube} VIDEO_ID :title: Video title for accessibility ::: Options: Option Default Description :title: (required) Accessible title for the iframe :width: 100% Container width (100%, 80%, 800px) :privacy: true Use youtube-nocookie.com :start: — Start time in seconds :end: — End time in seconds :autoplay: false Auto-start video :muted: false Start muted (required with autoplay) :loop: false Loop video :controls: true Show player controls :aspect: 16/9 Aspect ratio (16/9, 4/3, 21/9) :class: — Additional CSS classes Example: Examples Basic embed: :::{youtube} dQw4w9WgXcQ :title: Rick Astley - Never Gonna Give You Up ::: Live example: Watch on YouTube: Rick Astley - Never Gonna Give You Up With start time (starts at 43 seconds): :::{youtube} dQw4w9WgXcQ :title: Rick Astley - Never Gonna Give You Up (Chorus) :start: 43 ::: Live example: Watch on YouTube: Rick Astley - Never Gonna Give You Up (Chorus) With custom width (50%): :::{youtube} dQw4w9WgXcQ :title: Rick Astley - Never Gonna Give You Up :width: 50% ::: Live example: Watch on YouTube: Rick Astley - Never Gonna Give You Up (50% width) Vimeo Embed Vimeo videos with Do Not Track enabled by default. Syntax: :::{vimeo} VIDEO_ID :title: Video title for accessibility ::: Options: Option Default Description :title: (required) Accessible title for the iframe :width: 100% Container width (100%, 80%, 800px) :dnt: true Enable Do Not Track mode :color: — Player accent color (hex without #) :autopause: true Pause when another video starts :background: false Background mode (no controls) :autoplay: false Auto-start video :muted: false Start muted :loop: false Loop video :aspect: 16/9 Aspect ratio :class: — Additional CSS classes Example: Examples Basic embed: :::{vimeo} 203011020 :title: Beautiful Cinematic Video ::: Live example: Watch on Vimeo: Beautiful Cinematic Video With custom accent color: :::{vimeo} 203011020 :title: Beautiful Cinematic Video :color: 00adef ::: Live example: Watch on Vimeo: Beautiful Cinematic Video TikTok Embed TikTok videos. Ideal for blogs and social content. Syntax: :::{tiktok} VIDEO_ID :title: Video title for accessibility ::: Options: Option Default Description :title: (required) Accessible title for the iframe :width: 100% Container width (100%, 80%, 400px) :autoplay: false Auto-start video :muted: false Start muted :loop: false Loop video :aspect: 9/16 Aspect ratio (vertical by default) :class: — Additional CSS classes Example: Examples Basic embed: :::{tiktok} 7251756576833309995 :title: Bengal Cat Video ::: Live example: Watch on TikTok: Bengal Cat from @bengalsofbama Tip Tip TikTok video IDs are 19 digits. Find them in the URL: tiktok.com/@user/video/7251756576833309995 Self-Hosted Video Embed videos from your own server using HTML5 <video>. Syntax: :::{video} /path/to/video.mp4 :title: Video title for accessibility ::: Options: Option Default Description :title: (required) Accessible title :poster: — Poster image path :autoplay: false Auto-start video :muted: false Start muted :loop: false Loop video :controls: true Show player controls :preload: metadata Preload strategy (none, metadata, auto) :width: 100% Video width (px or %) :aspect: 16/9 Aspect ratio :class: — Additional CSS classes Supported formats: .mp4, .webm, .ogg, .mov Example: Examples Basic embed: :::{video} /assets/demo.mp4 :title: Product Demo ::: With poster and options: :::{video} /assets/demo.mp4 :title: Product Demo :poster: /assets/demo-poster.jpg :preload: auto ::: Figure (Images with Captions) Create semantic <figure> elements with optional captions, links, and alignment. Syntax: :::{figure} /path/to/image.png :alt: Descriptive alt text :caption: Optional caption text ::: Options: Option Default Description :alt: (required) Alt text (empty for decorative images) :caption: — Caption text below image :width: — Image width (80%, 500px) :height: — Image height :align: — Alignment (left, center, right) :link: — URL to link image to :target: — Link target (_blank for new tab) :loading: lazy Loading strategy (lazy, eager) :class: — Additional CSS classes Supported formats: .png, .jpg, .jpeg, .gif, .webp, .svg, .avif Example: Examples Basic figure with alt text: :::{figure} /images/architecture.png :alt: System architecture diagram showing component relationships ::: With caption and alignment: :::{figure} /images/screenshot.png :alt: Application dashboard :caption: The main dashboard showing key metrics :align: center :width: 80% ::: Linked image opening in new tab: :::{figure} /images/diagram.png :alt: Workflow diagram :link: https://example.com/full-diagram :target: _blank ::: Decorative image (empty alt): :::{figure} /images/decorative-border.png :alt: ::: Audio Embed self-hosted audio files using HTML5 <audio>. Syntax: :::{audio} /path/to/audio.mp3 :title: Audio title for accessibility ::: Options: Option Default Description :title: (required) Accessible title :autoplay: false Auto-start audio :muted: false Start muted :loop: false Loop audio :controls: true Show player controls :preload: metadata Preload strategy :class: — Additional CSS classes Supported formats: .mp3, .ogg, .wav, .flac, .m4a, .aac Example: Examples Basic audio: :::{audio} /assets/podcast-episode-1.mp3 :title: Episode 1 - Getting Started ::: Background audio: :::{audio} /assets/ambience.mp3 :title: Ambient sound :autoplay: true :loop: true :controls: false ::: Audio Streaming Embeds Spotify Embed Spotify tracks, albums, playlists, and podcast episodes. Syntax: :::{spotify} SPOTIFY_ID :title: Track/Album/Playlist title :type: track ::: The SPOTIFY_ID is the 22-character alphanumeric ID from the Spotify URL. For example, in https://open.spotify.com/track/4iV5W9uYEdYUVa79Axb7Rh, the ID is 4iV5W9uYEdYUVa79Axb7Rh. Options: Option Default Description :title: (required) Accessible title for iframe :type: track Content type: track, album, playlist, episode, show, artist :height: (auto) Embed height in pixels (auto-detected by type) :theme: 0 Color theme: 0 for dark, 1 for light :class: — Additional CSS classes Default heights by type: Type Height track 152px album, playlist, show, artist 352px episode 232px Example: Examples Track embed: :::{spotify} 13JAl3SvRcko5HgfwMU5q5 :title: CCTV by Phantoms & JEV :type: track ::: Listen on Spotify: CCTV by Phantoms & JEV Album embed: :::{spotify} 5xBJBxfQFowtJ5yq7MnXMG :title: HEAT by Tove Lo :type: album ::: Listen on Spotify: HEAT by Tove Lo Playlist embed: :::{spotify} 37i9dQZF1DXcBWIGoYBM5M :title: Today's Top Hits :type: playlist ::: Listen on Spotify: Today's Top Hits Podcast episode: :::{spotify} 4rOoJ6Egrf8K2IrywzwOMk :title: The Joe Rogan Experience Episode :type: episode ::: Listen on Spotify: The Joe Rogan Experience Episode Light theme: :::{spotify} 13JAl3SvRcko5HgfwMU5q5 :title: CCTV by Phantoms & JEV :type: track :theme: 1 ::: Listen on Spotify: CCTV by Phantoms & JEV SoundCloud Embed SoundCloud tracks and playlists. Syntax: :::{soundcloud} username/track-name :title: Track title ::: Use the path from the SoundCloud URL (everything after soundcloud.com/). You can also paste the full URL — the directive will extract the path automatically. Options: Option Default Description :title: (required) Accessible title for iframe :type: track Content type: track or playlist :height: (auto) Embed height in pixels (auto-detected by type) :color: ff5500 Accent color hex without # :autoplay: false Auto-start playback :hide_related: false Hide related tracks :show_comments: true Show comments :show_user: true Show uploader info :show_reposts: false Show reposts :visual: false Use visual player (larger artwork) :class: — Additional CSS classes Default heights by type: Type Height track 166px track (visual) 300px playlist 450px Example: Examples Track embed (from URL path): :::{soundcloud} user-604227447/celine-dion-the-whispers-im-alive-x-and-the-beat-goes-on-the-jammin-kid-mashup :title: I'm Alive x And The Beat Goes On (Mashup) ::: Listen on SoundCloud: I'm Alive x And The Beat Goes On (Mashup) Visual player: :::{soundcloud} user-604227447/celine-dion-the-whispers-im-alive-x-and-the-beat-goes-on-the-jammin-kid-mashup :title: I'm Alive x And The Beat Goes On (Mashup) :visual: true ::: Listen on SoundCloud: I'm Alive x And The Beat Goes On (Mashup) Custom accent color: :::{soundcloud} user-604227447/celine-dion-the-whispers-im-alive-x-and-the-beat-goes-on-the-jammin-kid-mashup :title: I'm Alive x And The Beat Goes On (Mashup) :color: 8b5cf6 ::: Listen on SoundCloud: I'm Alive x And The Beat Goes On (Mashup) Code Playground Embeds GitHub Gist Embed GitHub Gists with optional file selection. Syntax: :::{gist} USERNAME/GIST_ID :file: optional-filename.py ::: Options: Option Default Description :file: — Specific file from multi-file gist Example: Examples Basic gist: :::{gist} lbliii/21314a0babc8838bc2b5eecb53faec75 ::: Live example: View gist: lbliii/21314a0babc8838bc2b5eecb53faec75 Specific file from multi-file gist: :::{gist} octocat/12345678901234567890123456789012 :file: example.py ::: CodePen Embed CodePen pens. Syntax: :::{codepen} USERNAME/PEN_ID :title: Pen title for accessibility ::: Options: Option Default Description :title: (required) Accessible title :default-tab: result Default tab (html, css, js, result) :theme: dark Theme (dark, light) :height: 300 Embed height in pixels :editable: false Allow editing in embed :preview: true Show preview on load :class: — Additional CSS classes Example: Examples Basic embed: :::{codepen} mrdanielschwarz/VYaPVgr :title: CSS Animation Demo ::: Live example: See the Pen CSS Animation Demo by mrdanielschwarz on CodePen. With CSS tab visible: :::{codepen} mrdanielschwarz/VYaPVgr :title: CSS Animation Demo :default-tab: css :height: 400 ::: Live example: See the Pen CSS Animation Demo by mrdanielschwarz on CodePen. CodeSandbox Embed CodeSandbox projects. Syntax: :::{codesandbox} SANDBOX_ID :title: Sandbox title for accessibility ::: Options: Option Default Description :title: (required) Accessible title :module: — Initial file to open (/src/App.js) :view: split View mode (editor, preview, split) :height: 500 Embed height in pixels :fontsize: 14 Editor font size in pixels :hidenavigation: false Hide file navigation sidebar :theme: dark Color theme (dark, light) :class: — Additional CSS classes Example: Examples Basic embed: :::{codesandbox} new :title: New Sandbox ::: Live example: View on CodeSandbox: New Sandbox With preview only: :::{codesandbox} new :title: New Sandbox Preview :view: preview :height: 400 ::: Live example: View on CodeSandbox: New Sandbox Preview StackBlitz Embed StackBlitz projects. Syntax: :::{stackblitz} PROJECT_ID :title: Project title for accessibility ::: Options: Option Default Description :title: (required) Accessible title :file: — Initial file to open :view: both View mode (editor, preview, both) :height: 500 Embed height in pixels :hidenavigation: false Hide file navigation sidebar :hidedevtools: false Hide dev tools panel :class: — Additional CSS classes Example: Examples Basic embed: :::{stackblitz} vitejs-vite :title: Vite Starter Project ::: Live example: View on StackBlitz: Vite Starter Project With preview only: :::{stackblitz} vitejs-vite :title: Vite Starter Preview :view: preview :height: 400 ::: Live example: View on StackBlitz: Vite Starter Preview Terminal Recordings Asciinema Embed terminal recordings from asciinema.org or local .cast files. Syntax: Remote recording (asciinema.org): :::{asciinema} RECORDING_ID :title: Recording title for accessibility ::: Local recording file: :::{asciinema} recordings/demo.cast :title: Recording title for accessibility ::: Input: Numeric ID (e.g., 590029) for asciinema.org recordings File path ending in .cast (e.g., recordings/demo.cast) for local files Local files should be placed in your static/ directory Paths are resolved relative to site root (e.g., static/recordings/demo.cast → /recordings/demo.cast) Options: Option Default Description :title: (required) Accessible ARIA label :cols: 80 Terminal width in columns :rows: 24 Terminal height in rows :speed: 1.0 Playback speed multiplier :autoplay: false Auto-start playback :loop: false Loop recording :theme: asciinema Color theme name :poster: npt:0:0 Preview frame (npt:MM:SS format) :idle-time-limit: — Max idle time between frames (seconds) :start-at: — Start playback at specific time :class: — Additional CSS classes Example: Examples Basic embed: :::{asciinema} 590029 :title: Installing Bengal with pip ::: With custom size and speed: :::{asciinema} 590029 :title: Installing Bengal with pip :cols: 120 :rows: 30 :speed: 2.0 :autoplay: true ::: With custom theme and idle time limit: :::{asciinema} 590029 :title: Build process demo :theme: monokai :idle-time-limit: 2 :poster: npt:0:5 ::: Using a local recording file: :::{asciinema} recordings/install-demo.cast :title: Installation walkthrough :cols: 120 :speed: 1.5 :autoplay: true ::: Note: For local files, place your .cast files in the static/ directory (e.g., static/recordings/demo.cast). The directive will automatically load the asciinema player and initialize it with your local file. Accessibility Requirements All media embeds follow WCAG 2.1 AA guidelines: Required titles: All iframes require a :title: option for screen readers Alt text: Figures require :alt: text (use empty string for decorative images) Fallback content: All embeds include <noscript> fallbacks with direct links Keyboard navigation: Video/audio players support keyboard controls ARIA labels: Terminal recordings use role="img" and aria-label Privacy Features Media embeds are privacy-respecting by default: YouTube: Uses youtube-nocookie.com (disable with :privacy: false) Vimeo: Enables Do Not Track (disable with :dnt: false) No third-party tracking: Self-hosted options available for video, audio, figures Security All media directives validate inputs to prevent: XSS attacks: ID/URL validation rejects malicious input Path traversal: Local paths cannot escape content directory Iframe sandboxing: External embeds use restricted sandbox attributes Responsive Design All embeds use CSS aspect-ratio for fluid responsive layouts: .video-embed iframe, .video-embed video { aspect-ratio: var(--video-aspect, 16/9); } Override the aspect ratio with the :aspect: option or custom CSS classes. Related Layout Directives - Cards, tabs, grids Interactive Directives - Code tabs, data tables Hugo Migration - Migrating from Hugo shortcodes -------------------------------------------------------------------------------- Metadata: - Author: lbliii - Word Count: 2027 - Reading Time: 10 minutes