This revision of the shortcode also handles videos uploaded prior to v6.1.0 (i.e., those without an aspect ratio in the initial API response). We have to make a secondary API call (which isn’t great), but (a) it shouldn’t be required too often, and (b) we cache the result of the API call(s).
layouts/_shortcodes/peertube.html
{{- /*
Embeds a PeerTube video.
@param {string} url The URL of the PeerTube video.
@param {string} [start] The time, from the start of the video, when the player should start playing the video (e.g., 42s, 6m7s).
@param {string} [stop] The time, from the start of the video, when the player should stop playing the video (e.g., 42s, 6m7s).
@param {string} [loading=eager] The loading attribute of the iframe element, either eager or lazy. Default is eager.
@param {int} [width=0] The width of the video in pixels. Responsive if `0`.
@param {bool} [allowFullScreen=true] Whether to allow full screen playback.
@param {bool} [autoplay=false] Whether to automatically play the video. Forces mute to true.
@param {bool} [controls=true] Whether to display the video controls.
@param {bool} [displayLink=true] Whether to display the PeerTube link.
@param {bool} [displayTitle=true] Whether to display the video title.
@param {bool} [displayWarning=true] Whether to display the privacy warning.
@param {bool} [loop=false] Whether to indefinitely repeat the video.
@param {bool} [mute=false] Whether to mute the video. Always true when autoplay is true.
@param {bool} [p2p=true] Whether to enable peer-to-peer bandwidth sharing.
@returns {template.HTML}
@link https://docs.joinpeertube.org/api/embed-player
@example {{< peertube url="https://toobnix.org/w/5jBegFpNbffA1nhmp32kqR" >}}
*/}}
{{- /* Set constants. */}}
{{- $trueValues := slice "true" true 1 }}
{{- $falseValues := slice "false" false 0 }}
{{- $sandbox := "allow-same-origin allow-scripts allow-popups allow-forms" }}
{{- /* Set defaults. */}}
{{- $url := "" }}
{{- $start := "" }}
{{- $stop := "" }}
{{- $loading := "eager" }}
{{- $width := 0 }}
{{- $height := 0 }}
{{- $allowFullScreen := true }}
{{- $autoplay := false }}
{{- $controls := true }}
{{- $displayLink := true }}
{{- $displayTitle := true }}
{{- $displayWarning := true }}
{{- $loop := false }}
{{- $mute := false }}
{{- $p2p := true }}
{{- /* Get parameters. */}}
{{- $url = or (.Get "url") $url }}
{{- $start := or (.Get "start") $start }}
{{- $stop := or (.Get "stop") $stop }}
{{- $width = or (.Get "width") $width | int }}
{{- $loading := or (.Get "loading") $loading }}
{{- if in $trueValues (.Get "allowFullScreen") }}
{{- $allowFullScreen = true }}
{{- else if in $falseValues (.Get "allowFullScreen") }}
{{- $allowFullScreen = false }}
{{- end }}
{{- if in $trueValues (.Get "autoplay") }}
{{- $autoplay = true }}
{{- else if in $falseValues (.Get "autoplay") }}
{{- $autoplay = false }}
{{- end }}
{{- if in $trueValues (.Get "controls") }}
{{- $controls = true }}
{{- else if in $falseValues (.Get "controls") }}
{{- $controls = false }}
{{- end }}
{{- if in $trueValues (.Get "displayLink") }}
{{- $displayLink = true }}
{{- else if in $falseValues (.Get "displayLink") }}
{{- $displayLink = false }}
{{- end }}
{{- if in $trueValues (.Get "displayTitle") }}
{{- $displayTitle = true }}
{{- else if in $falseValues (.Get "displayTitle") }}
{{- $displayTitle = false }}
{{- end }}
{{- if in $trueValues (.Get "displayWarning") }}
{{- $displayWarning = true }}
{{- else if in $falseValues (.Get "displayWarning") }}
{{- $displayWarning = false }}
{{- end }}
{{- if in $trueValues (.Get "loop") }}
{{- $loop = true }}
{{- else if in $falseValues (.Get "loop") }}
{{- $loop = false }}
{{- end }}
{{- if in $trueValues (.Get "mute") }}
{{- $mute = true }}
{{- else if in $falseValues (.Get "mute") }}
{{- $mute = false }}
{{- end }}
{{- if in $trueValues (.Get "p2p") }}
{{- $p2p = true }}
{{- else if in $falseValues (.Get "p2p") }}
{{- $p2p = false }}
{{- end }}
{{- /* Mute if autoplay enabled. */}}
{{- if $autoplay }}
{{- $mute = true }}
{{- end }}
{{- if $url }}
{{- /* Determine API URL. */}}
{{- $u := urls.Parse $url }}
{{- $pathSegments := strings.Split $u.Path "/" }}
{{- $shortUUID := index $pathSegments (sub (len $pathSegments) 1) }}
{{- $api := fmt.Printf "%s://%s/api/v1/videos/%s" $u.Scheme $u.Host $shortUUID }}
{{- /* Get data from API. */}}
{{- $data := "" }}
{{- with try (resources.GetRemote $api) }}
{{- with .Err }}
{{- errorf "%s" . }}
{{- else with .Value }}
{{- $data = . | transform.Unmarshal }}
{{- /* Handle null aspect ratio for videos uploaded prior to PeerTube API v6.1.0. */}}
{{- if not $data.aspectRatio }}
{{- $aspectRatio := partial "inline/peertube/get-aspect-ratio.html" (dict "data" $data "name" $.Name "position" $.Position) }}
{{- $data = merge $data (dict "aspectRatio" $aspectRatio) }}
{{- end }}
{{- else }}
{{- warnidf "shortcode-peertube" "The %q shortcode was unable to retrieve the remote data. See %s" $.Name $.Position }}
{{- end }}
{{- end }}
{{- if $data }}
{{- /* Build src attribute. */}}
{{- $qsp := dict
"autoplay" (cond $autoplay 1 0)
"controlBar" (cond $controls 1 0)
"loop" (cond $loop 1 0)
"muted" (cond $mute 1 0)
"peertubeLink" (cond $displayLink 1 0)
"p2p" (cond $p2p 1 0)
"title" (cond $displayTitle 1 0)
"warningTitle" (cond $displayWarning 1 0)
}}
{{- with $start }}
{{- $qsp = merge $qsp (dict "start" .) }}
{{- end }}
{{- with $stop }}
{{- $qsp = merge $qsp (dict "stop" .) }}
{{- end }}
{{- $qs := collections.Querify $qsp }}
{{- $src := fmt.Printf "%s://%s%s?%s" $u.Scheme $u.Host $data.embedPath $qs }}
{{- /* Render. */}}
{{- if $width }}
{{- $height = div $width $data.aspectRatio | math.Round }}
<iframe
{{- if $allowFullScreen }} allowfullscreen {{- end }}
width="{{ $width }}"
height="{{ $height }}"
frameborder="0"
loading="{{ $loading }}"
title="{{ $data.name }}"
sandbox="{{ $sandbox }}"
src="{{ $src }}"
></iframe>
{{- else }}
{{- $width = "100%" }}
{{- $height = "100%" }}
{{- $paddingTop := $data.aspectRatio | div 1 | mul 100 | fmt.Printf "%2.2f%%" }}
<div style="position: relative; padding-top: {{ $paddingTop }};">
<iframe
{{- if $allowFullScreen }} allowfullscreen {{- end }}
width="{{ $width }}"
height="{{ $height }}"
frameborder="0"
loading="{{ $loading }}"
title="{{ $data.name }}"
sandbox="{{ $sandbox }}"
style="position: absolute; inset: 0px;"
src="{{ $src }}"
></iframe>
</div>
{{- end }}
{{- end }}
{{- else }}
{{- errorf "The %q shortcode requires a %q argument. See %s" .Name "url" .Position }}
{{- end -}}
{{- define "_partials/inline/peertube/get-aspect-ratio.html" }}
{{- $aspectRatio := 0 }}
{{- $metadataUrl := "" }}
{{- range .data.streamingPlaylists }}
{{- range .files }}
{{- if .hasVideo }}
{{- $metadataUrl = .metadataUrl }}
{{- break }}
{{- end }}
{{- end }}
{{- if $metadataUrl }}
{{- break }}
{{- end }}
{{- end }}
{{- with $metadataUrl }}
{{- with try (resources.GetRemote .) }}
{{- with .Err }}
{{- errorf "%s" . }}
{{- else with .Value }}
{{- with . | transform.Unmarshal }}
{{- range .streams }}
{{- if and .width .height }}
{{- $aspectRatio = div .width .height }}
{{- break }}
{{- end }}
{{- end }}
{{- if not $aspectRatio }}
{{- errorf "The %q shortcode was unable to determine the aspect ratio. See %s" $.name $.position }}
{{ end }}
{{- end }}
{{- else }}
{{- errorf "The %q shortcode was unable to retrieve the metadata. See %s" $.name $.position }}
{{- end }}
{{- end }}
{{- else }}
{{- errorf "The %q shortcode was unable to determine the metadata URL. See %s" $.name $.position }}
{{- end }}
{{- return $aspectRatio }}
{{- end -}}
I’ve also updated the example repo:
git clone --single-branch -b hugo-github-issue-13280 https://github.com/jmooring/hugo-testing hugo-github-issue-13280
cd hugo-github-issue-13280
hugo server