跳到主要内容

track

2023年11月06日
柏拉文
越努力,越幸运

一、认识


<track> 被当作媒体元素—<audio><video>的子元素来使用。它允许指定时序文本字幕(或者基于时间的数据),例如自动处理字幕。字幕格式有 WebVTT 格式 (en-US)(.vtt格式文件)— Web 视频文本字幕格式,以及指时序文本标记语言(TTML)格式。

二、语法


<video controls src="./test.mp4">
<track default kind="subtitles" srclang="zh-cn" label="简体中文" src="./Simplified Chinese.vtt"></track>
<track kind="subtitles" srclang="en-us" label="English" src="./English.vtt"></track>
</video>

三、用法


3.1 srt 转换为 vtt , 动态插入到 video

<video controls src="./assets/test.mp4"></video>
<script type="module">
const videoEl = document.querySelector('video');
const trackElList = [];
const trackSubtitle = [
{
id: 'zh-cn',
label: '简体中文(原始语言)',
isDefault: true,
file_url: 'http://127.0.0.1:5500/umu-subtitle/example/assets/zh-cn.srt',
},
{
id: 'en-us',
label: 'English',
file_url: 'http://127.0.0.1:5500/umu-subtitle/example/assets/en-us.srt',
}
]

function getFile(url){
const urlObj = new URL(url);
urlObj.searchParams.append('_from', location.host);
return fetch(urlObj.toString()).then((response) => {
return response.text();
}).catch((error) => {
console.error(error);
return '';
});
}

function getVttFile(srtContent){
const vttstr = ('WEBVTT\r\n\r\n' + srtContent).replace(/(\d{2}:\d{2}:\d{2}),(\d{3})/g, '$1.$2').replace(/\r?\n\d+\r?\n/g, '\r\n');
const blob = new Blob([vttstr], { type: 'text/vtt' });

// blob 数据转换为 base64 格式地址
return new Promise((resolve, reject) => {
fileReader.onload = e => {
resolve(e.target.result);
};
fileReader.readAsDataURL(blob);
fileReader.onerror = () => {
reject(new Error('blobToBase64 error'));
};
});
// blob 数据转换为 blob 格式地址
return URL.createObjectURL(blob);
}

async function loadSubtitle(resUrl,trackEl) {
const srtResult = await getFile(resUrl);
const vttResult = await getVttFile(srtResult)
trackEl.src = vttResult;
}

async function createTrackElementBase(videoEl, data){
const { id, label, srcLang, file_url, isDefault } = data;
const trackEl = document.createElement('track');
trackEl.setAttribute('class', 'umu-subtitle-track');
trackEl.setAttribute('kind', 'subtitles');
trackEl.setAttribute('label', label);
trackEl.setAttribute('srclang', id);
isDefault && trackEl.setAttribute('default', true);
loadSubtitle(file_url,trackEl);
videoEl.appendChild(trackEl);
trackElList.push(trackEl);
}

function createTrackElement(videoEl,trackSubtitle){
trackSubtitle.forEach((item)=>{
createTrackElementBase(videoEl,{
...item,
});
});
}

function closeTrackSubtitle(id,active){
const index = Array.from(videoEl.textTracks).findIndex(item=> item.language === id);

if(index != -1){
videoEl.textTracks[index].mode = active ? 'showing' : 'hidden';
}
}

createTrackElement(videoEl,trackSubtitle);
closeTrackSubtitle('zh-cn',false);
</script>