跳到主要内容

vtt

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

一、认识


二、格式


WEBVTT

00:00:00.460 --> 00:00:10.430
小女子不才,未得公子进来扰公子良久,公子勿快。

00:00:11.470 --> 00:00:19.310
公子向北走,小女子向南瞧,此生就此别过了,

00:00:19.750 --> 00:00:32.870
难以忘怀。愿你三冬暖,愿你春冬寒,愿你真黑又灯,

00:00:33.580 --> 00:00:42.260
夏日有伞,愿你善青山,愿你一良人暖。

00:00:43.100 --> 00:00:43.710
抖音。

三、操作


3.1 获取字幕内容

function getSubtitleContent(url){
return fetch(url).then((response)=>{
return response.text();
}).catch((error=>{
return ""
}));
}

3.2 解析字幕内容

const REG_LINE_CUT = /\r?\n/; 
const REG_TIME_S = /^(\d{2}):(\d{2}):(\d{2}),(\d{3})$/;
const REG_TIME = /^(\d{2}:\d{2}:\d{2},\d{3})[\s->]+(\d{2}:\d{2}:\d{2},\d{3})$/;

function parseDuration(str){
try {
if (REG_TIME_S.test(str)) {
return Number(RegExp.$1) * 60 * 60 * 1000 + Number(RegExp.$2) * 60 * 1000 + Number(RegExp.$3) * 1000 + Number(RegExp.$4);
}
} catch (err) {
return 0;
}

}

function parseSubtitleContent(content){
try {
const sourceLines = content.split(REG_LINE_CUT);
const subtitleData = [];
let index, tmpIndex, time, txt = [], i = 0;
while (i < sourceLines.length) {
const cline = sourceLines[i].replace(/^\s+|\s+$/g, '');
i++;
// 空内容
if(!cline) {
continue;
}

// 数字
if (/^\d+$/.test(cline)) {
if (tmpIndex) { // 上一行也是数字,则并入txt
txt.push(tmpIndex);
tmpIndex = '';
}
tmpIndex = Number(cline);
continue;
}

// 时间段范围
if (REG_TIME.test(cline)) {
const startStr = RegExp.$1;
const endStr = RegExp.$2;
// push上一条字幕数据
if (time) {
subtitleData.push({
index,
...time,
content: txt.join('\n'),
});
}
// 新的一条字幕数据
index = tmpIndex;
tmpIndex = '';
txt = [];
time = {
start: parseDuration(startStr),
startStr,
end: parseDuration(endStr),
endStr,
};
continue;
}

if (tmpIndex) { // 上一行是数字,切不满足上面条件,认为是内容,并入txt
txt.push(tmpIndex);
tmpIndex = '';
}
txt.push(cline);
}
// 处理最后一条
if (time) {
// 最后一行字幕内容可能是数字的情况
if (tmpIndex) {
txt.push(tmpIndex);
}
subtitleData.push({
index,
...time,
content: txt.join('\n'),
});
}
return subtitleData;
} catch (error) {
console.warn(error);
return [];
}
}

3.3、转换字幕格式 srt-vtt

function transformSrtToVtt(content) {
const vttstr = ('WEBVTT\r\n\r\n' + content)
.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' });
const fileReader = new FileReader();

// 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);
}