Reputation: 1
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 enableTextTrack
method 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