如何检测视频字幕轨道选择并设置用户偏好Cookie?
问题描述
我们网站的<video>标签内包含<track>形式的字幕,部分视频仅含一个label="English"、srclang="en"的英文字幕,部分视频还会额外包含label="Cymraeg"、srclang="cy"的威尔士语字幕。需求是将用户的字幕偏好存入Cookie:
- 关闭字幕时,设置
cookies['caption_prefs'] = "off" - 开启英文字幕时设为
"en" - 开启威尔士语字幕时设为
"cy"
最初尝试结合jQuery与原生JS监听字幕变化,代码如下:
var video, video_tag, tracks; $('video').each(function(){ video = $(this); video_tag = video.get(0); tracks = video_tag.textTracks; tracks.addEventListener('change', function(event){ console.log('subtitles changed'); }); });
这段代码能触发字幕变化的日志,但无法获取用户选择的具体选项,想确认是否可以完全用jQuery实现?
后续调整了事件逻辑:
tracks.addEventListener('change', function(event){ for (let i = 0; i < tracks.length; i++) { console.log("subtitles changed: "+tracks[i].language+": "+tracks[i].mode); } });
输出示例:
//字幕关闭时 subtitles changed: en: disabled subtitles changed: cy: disabled //选择cy字幕时 subtitles changed: en: disabled subtitles changed: cy: showing
现在打算通过找到第一个mode为"showing"的track获取其language值,无匹配项则设为"off"来设置Cookie,想验证这个实现是否合理。
解决方案与验证
关于「完全用jQuery实现」:
不行,因为textTracks是原生HTMLVideoElement的专属属性,jQuery没有对其做封装,必须通过get(0)或直接取DOM元素的方式,拿到原生视频对象后才能操作字幕轨道。你的实现思路合理性:
这个思路是完全可行的:- 字幕切换时遍历所有textTrack,找到
mode === 'showing'的轨道,取其language作为Cookie值 - 当所有轨道的
mode都是disabled时,设置Cookie为"off"
- 字幕切换时遍历所有textTrack,找到
优化补充:
- 可以用数组方法简化遍历逻辑,代码更简洁
- 设置Cookie时建议添加有效期,让用户偏好持久化
- 页面加载时读取Cookie,自动恢复用户之前的字幕选择,提升体验
完整示例代码
// 监听字幕变化并设置Cookie $('video').each(function(){ const videoTag = this; // 直接获取原生DOM元素,简化代码 const tracks = videoTag.textTracks; // 监听字幕切换事件 tracks.addEventListener('change', function(){ const activeTrack = Array.from(tracks).find(track => track.mode === 'showing'); const captionPref = activeTrack ? activeTrack.language : 'off'; // 设置Cookie,有效期30天,全站生效 document.cookie = `caption_prefs=${captionPref}; expires=${new Date(Date.now() + 30*24*60*60*1000).toUTCString()}; path=/`; }); // 页面加载时恢复用户之前的字幕偏好 const savedPref = document.cookie.split('; ').find(row => row.startsWith('caption_prefs='))?.split('=')[1]; if(savedPref){ if(savedPref === 'off'){ // 关闭所有字幕 Array.from(tracks).forEach(track => track.mode = 'disabled'); } else { // 找到目标字幕轨道并开启 const targetTrack = Array.from(tracks).find(track => track.language === savedPref); if(targetTrack){ targetTrack.mode = 'showing'; // 关闭其他字幕轨道 Array.from(tracks).forEach(track => { if(track !== targetTrack) track.mode = 'disabled'; }); } } } });
内容的提问来源于stack exchange,提问作者Max Williams
相关产品推荐
相关产品推荐

