Douglas
Douglas

Reputation: 1

How do I resolve "InvalidTrackLanguageError" when trying to enable English subtitles?

I want to create a custom button in my Vue component that, when clicked, toggles subtitles (also known as Closed Captions or CC) on or off in an embedded Vimeo video player.

To do this, I am trying to use the Vimeo Player API. The Vimeo Player API provides methods for enabling and disabling text tracks, which I can use to turn subtitles on and off.

However, I am encountering an issue where the Vimeo Player API's enableTextTrackmethod is throwing an InvalidTrackLanguageError: There are no tracks for “SUBTITLES” error. This error indicates that the video does not have a subtitle track available.

To resolve this issue, I tried adding a check before enabling the subtitle track to ensure that a subtitle track is available. I did this by using the Vimeo Player API's getTextTracks method to get all available text tracks, and then checking if there is an English subtitle track.

However, even with this check, I am still getting the InvalidTrackLanguageError error. This suggests that the video may not have an English subtitle track available, or that there may be an issue with how I am using the Vimeo Player API.

<template>
  <div ref="elementRef" />
</template>
<script>
import {
  watch,
  toRefs,
  onMounted,
  onBeforeUnmount,
  ref,
  unref,
  toRef
} from 'vue'
import Player from '@vimeo/player'

function emitVueEvent({ player, event, emit }) {
  player.on(event, (data) => emit(event, data, player))
}

const eventsToEmit = [
  'play',
  'playing',
  'pause',
  'ended',
  'timeupdate',
  'progress',
  'seeking',
  'seeked',
  'texttrackchange',
  'chapterchange',
  'cuechange',
  'cuepoint',
  'volumechange',
  'playbackratechange',
  'bufferstart',
  'bufferend',
  'error',
  'loaded',
  'durationchange',
  'fullscreenchange',
  'qualitychange',
  'camerachange',
  'resize'
]

export default {
  name: 'VimeoPlayer',
  props: {
    playerHeight: {
      type: Number,
      default: 320
    },
    playerWidth: {
      type: Number,
      default: 640
    },
    options: {
      type: Object,
      default: () => ({})
    },
    videoId: {
      type: String,
      default: ''
    },
    videoUrl: {
      type: String,
      default: ''
    },
    loop: {
      type: Boolean,
      default: false
    },
    autoplay: {
      type: Boolean,
      default: false
    },
    controls: {
      type: Boolean,
      default: true
    },
    eventsToEmit: {
      type: Array,
      default: () => eventsToEmit
    }
  },
  setup(props, { emit }) {
    let player
    let ccEnabled = false

    const toggleCC = () => {
      if (ccEnabled) {
        player.disableTextTrack().then(() => {
          ccEnabled = false
        })
      } else {
        player.getTextTracks().then((tracks) => {
          const englishSubtitlesTrack = tracks.find(
            (track) =>
              track.language === 'en-x-autogen' && track.kind === 'subtitles'
          )
          if (englishSubtitlesTrack) {
            player.enableTextTrack('subtitles', 'en-x-autogen').then(() => {
              ccEnabled = true
            })
          } else {
            console.log('No English subtitles track available')
          }
        })
      }
    }
    const elementRef = ref(null)
    const { videoId, videoUrl } = toRefs(props)
    if (!props.videoId && !props.videoUrl) {
      console.warn(
        '[VueVimeoPlayer: You must provide at least a videoId or a videoUrl prop]'
      )
    }

    const mergeOptions = ({ id, url }) => {
      const opts = {
        width: props.playerWidth,
        height: props.playerHeight,
        loop: props.loop,
        autoplay: props.autoplay,
        controls: props.controls
      }
      if (unref(url)) {
        opts.url = unref(url)
      }
      if (unref(id)) {
        opts.id = unref(id)
      }
      return Object.assign(opts, props.options)
    }

    const play = () => player.play()
    const pause = () => player.pause()
    const mute = () => player.setVolume(0)
    const unmute = (volume = 0.5) => player.setVolume(volume)

    const setEvents = () => {
      player
        .ready()
        .then(() => {
          emit('ready', player)
        })
        .catch((error) => {
          emit('error', error, player)
        })

      props.eventsToEmit.forEach((event) =>
        emitVueEvent({ player, event, emit })
      )
    }

    onMounted(async () => {
      player = new Player(
        elementRef.value,
        mergeOptions({ id: props.videoId, url: props.videoUrl })
      )
      // Wait for the player to be ready
      await player.ready()

      // Add a delay to give time for the text tracks to load
      setTimeout(() => {
        player.getTextTracks().then((tracks) => {
          const englishSubtitlesTrack = tracks.find(
            (track) =>
              track.language === 'en-x-autogen' && track.kind === 'captions'
          )
          if (englishSubtitlesTrack) {
            console.log(
              'English subtitles track is available:',
              englishSubtitlesTrack
            )
          } else {
            console.log('No English subtitles track available')
          }
        })
      }, 2000) // Adjust the delay as needed

      console.log(player.getTextTracks())

      setEvents()
    })

    onBeforeUnmount(() => player.unload())

    watch(videoId, (id) => player.loadVideo(mergeOptions({ id })))
    watch(videoUrl, (url) => player.loadVideo(mergeOptions({ url })))
    watch(toRef(props, 'controls'), () =>
      player.loadVideo(mergeOptions({ url: videoUrl, id: videoId }))
    )

    const update = (id) => player.loadVideo(mergeOptions({ id }))

    return {
      update,
      play,
      pause,
      mute,
      unmute,
      elementRef,
      player,
      toggleCC
    }
  }
}
</script>

This is the button into the page I'm trying to use it

        <VimeoPlayer
          v-if="videoUrl"
          ref="vimeoPlayer"
          :video-url="videoUrl"
          :options="{ ...vimeoPlayerSize, allowfullscreen: true }"
          @ready="onReady"
          @chapterchange="onChapterChange"
          @ended="onEnded"
        />
        <button @click="$refs.vimeoPlayer.toggleCC">Toggle CC</button>

Upvotes: 0

Views: 45

Answers (0)

Related Questions