Hugo Peertube Shortcode

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
1 Like