You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
7.9 KiB
208 lines
7.9 KiB
9 months ago
|
---
|
||
|
title: B站字幕转换
|
||
|
date: 2022-02-22 10:34:50
|
||
|
toc: false
|
||
|
---
|
||
|
{% raw %}
|
||
|
<!DOCTYPE html>
|
||
|
<html>
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<meta http-equiv="Pragma" content="no-cache">
|
||
|
<meta http-equiv="Cache-Control" content="no-cache">
|
||
|
<meta http-equiv="Expires" content="0">
|
||
|
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
|
||
|
<!-- import Vue before Element -->
|
||
|
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
|
||
|
<!-- import JavaScript -->
|
||
|
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
|
||
|
</head>
|
||
|
<body>
|
||
|
<div id="app">
|
||
|
<div class="tools-upload">
|
||
|
<el-upload action="#" :http-request="requestUpload" :show-file-list="false">
|
||
|
<el-button size="mini" type="primary">上传</el-button>
|
||
|
</el-upload>
|
||
|
<div class="tools-right">
|
||
|
<div class="tool-item">
|
||
|
文件编码:
|
||
|
<el-select size="mini" v-model="fileEncoder" placeholder="文件编码">
|
||
|
<el-option label="GBK" value="GBK"></el-option>
|
||
|
<el-option label="UTF-8" value="UTF-8"></el-option>
|
||
|
<el-option label="GB2312" value="GB2312""></el-option>
|
||
|
</el-select>
|
||
|
</div>
|
||
|
<div class="tool-item">
|
||
|
换行符:
|
||
|
<el-select size="mini" v-model="newline" placeholder="换行符">
|
||
|
<el-option label="\r\n (Windows)" value="windows"></el-option>
|
||
|
<el-option label="\n (Linux)" value="linux"></el-option>
|
||
|
</el-select>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<el-input type="textarea" placeholder="请上传或输入字幕文件" v-model="originText" rows="15" show-word-limit="">
|
||
|
</el-input>
|
||
|
<div class="tools-btn">
|
||
|
<el-button size="mini" @click="generateSrt">生成SRT文件</el-button>
|
||
|
<el-button size="mini" @click="generateTXT">生成TXT文件</el-button>
|
||
|
<el-button size="mini" @click="clear">清空</el-button>
|
||
|
</div>
|
||
|
<el-input type="textarea" placeholder="等待生成SRT文件" v-model="srtText" rows="15" show-word-limit="">
|
||
|
</el-input>
|
||
|
<el-button type="text" @click="saveSrt">保存到本地</el-button>
|
||
|
|
||
|
<h3>字幕提取方法参考下面的视频</h3>
|
||
|
|
||
|
<div style="position: relative; padding: 30% 50%;">
|
||
|
<iframe src="//player.bilibili.com/player.html?aid=863543343&bvid=BV16G4y1S7Hp&cid=985575449&page=1&as_wide=1&high_quality=1&danmaku=1"
|
||
|
scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"
|
||
|
style="position: absolute; width: 100%; height: 100%; left: 0; top: 0;"></iframe>
|
||
|
</div>
|
||
|
</div>
|
||
|
</body>
|
||
|
<script>
|
||
|
|
||
|
new Vue({
|
||
|
el: '#app',
|
||
|
data: function () {
|
||
|
return {
|
||
|
fileEncoder: "UTF-8",
|
||
|
newline: "windows",
|
||
|
originText: "",
|
||
|
srtText: "",
|
||
|
fileName: ""
|
||
|
}
|
||
|
},
|
||
|
methods: {
|
||
|
// 覆盖默认的上传行为
|
||
|
requestUpload(content) {
|
||
|
let file = content.file
|
||
|
let index = file.name.lastIndexOf('.')
|
||
|
this.fileName = file.name.substring(0, index)
|
||
|
// 新建一个FileReader
|
||
|
const reader = new FileReader()
|
||
|
// 读取文件
|
||
|
reader.readAsText(file, this.fileEncoder)
|
||
|
// 读取完文件之后会回来这里
|
||
|
reader.onload = (e) => {
|
||
|
// 读取文件内容
|
||
|
const fileString = e.target.result
|
||
|
// 接下来可对文件内容进行处理
|
||
|
this.originText = fileString
|
||
|
}
|
||
|
},
|
||
|
generateSrt() {
|
||
|
this.srtText = ""
|
||
|
let originObj = JSON.parse(this.originText)
|
||
|
let body = originObj.body
|
||
|
let lastTo = null
|
||
|
for (let index = 0; index < body.length; index++) {
|
||
|
let line = body[index]
|
||
|
this.srtText += (index + (this.newline == 'windows' ? '\r\n' : '\n'))
|
||
|
let from = line.from
|
||
|
if (lastTo) {
|
||
|
let timeA = (from + '').split(".");
|
||
|
let timeB = (lastTo + '').split("."); //上次的时间
|
||
|
if (parseInt(timeB[0]) >= parseInt(timeA[0])) {
|
||
|
timeA[0] = timeB[0];
|
||
|
if (timeB[1]) {
|
||
|
if (parseInt(timeB[1]) >= parseInt(timeA[1])) {
|
||
|
timeA[1] = timeB[1];
|
||
|
}
|
||
|
}
|
||
|
from = (timeA[1] ? (timeA[0] + '.' + timeA[1]) : timeA[0])
|
||
|
}
|
||
|
}
|
||
|
this.srtText += (this.deelTime(from) + " --> ")
|
||
|
let to = line.to
|
||
|
lastTo = to
|
||
|
this.srtText += (this.deelTime(to) + (this.newline == 'windows' ? '\r\n' : '\n'))
|
||
|
this.srtText += line.content
|
||
|
this.srtText += (this.newline == 'windows' ? '\r\n' : '\n')
|
||
|
this.srtText += (this.newline == 'windows' ? '\r\n' : '\n')
|
||
|
}
|
||
|
},
|
||
|
generateTXT() {
|
||
|
this.srtText = ""
|
||
|
let originObj = JSON.parse(this.originText)
|
||
|
let body = originObj.body
|
||
|
let lastTo = null
|
||
|
for (let index = 0; index < body.length; index++) {
|
||
|
let line = body[index]
|
||
|
let content = line.content
|
||
|
this.srtText += content
|
||
|
this.srtText += (this.newline == 'windows' ? '\r\n' : '\n')
|
||
|
}
|
||
|
},
|
||
|
deelTime(origin) {
|
||
|
let timeA = (origin + '').split(".");
|
||
|
let tranTime = this.sumSecondToTime(timeA[0]);
|
||
|
return tranTime + "," + (timeA.length < 2 ? '000' : timeA[1].padStart(3, '0'));
|
||
|
},
|
||
|
|
||
|
sumSecondToTime(sumSecond) {
|
||
|
if (sumSecond <= 0) {
|
||
|
return "00:00:00";
|
||
|
}
|
||
|
let h = parseInt(sumSecond / 3600);
|
||
|
let m = parseInt((sumSecond - h * 3600) / 60);
|
||
|
let s = sumSecond - h * 3600 - m * 60;
|
||
|
let time = (h + '').padStart(2, '0') + ':' + (m + '').padStart(2, '0') + ':' + (s + '').padStart(2,
|
||
|
'0');
|
||
|
return time;
|
||
|
},
|
||
|
clear() {
|
||
|
this.originText = ""
|
||
|
},
|
||
|
saveSrt() {
|
||
|
// const file = new Blob(this.srtText, {
|
||
|
// type: 'text/plain'
|
||
|
// });
|
||
|
// a.href = URL.createObjectURL(file);
|
||
|
// a.download = name;
|
||
|
|
||
|
var element = document.createElement('a');
|
||
|
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(this.srtText));
|
||
|
if (this.fileName != '') {
|
||
|
element.setAttribute('download', this.fileName + '.srt');
|
||
|
} else {
|
||
|
element.setAttribute('download', 'translated.srt');
|
||
|
}
|
||
|
|
||
|
element.style.display = 'none';
|
||
|
document.body.appendChild(element);
|
||
|
element.click();
|
||
|
document.body.removeChild(element);
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
|
||
|
</script>
|
||
|
<style>
|
||
|
.tools-upload {
|
||
|
margin: 10px 0;
|
||
|
display: flex;
|
||
|
flex-direction: row;
|
||
|
justify-content: space-between;
|
||
|
align-items: center;
|
||
|
}
|
||
|
|
||
|
.tools-right {
|
||
|
display: flex;
|
||
|
flex-direction: row;
|
||
|
align-items: center;
|
||
|
font-size: 15px;
|
||
|
}
|
||
|
|
||
|
.tool-item {
|
||
|
margin-left: 10px;
|
||
|
}
|
||
|
|
||
|
.tools-btn {
|
||
|
margin: 10px 0;
|
||
|
}
|
||
|
</style>
|
||
|
</html>
|
||
|
{% endraw %}
|