
字幕是电影数据中被低估的部分,但是却导致效率低下。 最有趣的部分是音频信息的文学转录,提供了一种使电影可搜索的方法。
对于不耐烦的人,可以在这里找到示例:
https://github.com/azcoppen/subtitle-json/tree/master/json
现有标准
至少有8种不同的字幕格式经常使用。 SubRip(.srt)是迄今为止下载文件使用最广泛的方法。
- VOB(DVD)
- PGS(蓝光)
- SubRip(.srt)
- WebVTT(.vtt)
- 变电站Alpha(.ass)
- YouTube字幕(.sbv)
- JSON(TED.com)字幕(.json)
- TTML(.dfxp)
“ The Shawshank Redemption”中的示例.srt条目:
119
00:08:51,565 --> 00:08:54,943
So, when Andy Dufresne came to me in 1949
120
00:08:55,027 --> 00:08:58,363
and asked me to smuggle Rita Hayworth
into the prison for him,
121
00:08:58,447 --> 00:09:00,532
I told him, "No problem."
值得注意的问题
很少或没有编程访问数据
为了挖掘或搜索字幕转录内容,访问必须采用易于反序列化为简单且可用的对象模型的格式。 字幕(如剧本)以标记的格式进行格式化,该标记描述了重叠的时间,但其中的内容没有任何变化。 作为数据访问它可以在程序和平台之间进行更复杂的交换,并可以动态生成/操作文档。
每个国家一个文件?
同一部电影有多个国家档案完全没有意义。 尽管翻译发生在不同地方的不同时间,但每个设备或发行版只有一个文件似乎更加实用。
不同版本的数量令人困惑:
http://www.yifysubtitles.com/movie-imdb/tt0111161
版本中的内容不一致
在法国发行的电影可能与在美国发行的电影有所不同。 蓝光特别版可能与美国DVD不同。 “导演剪辑”的长度可能完全不同。
版本中的时间不一致
每个翻译的文件都以毫秒为单位存储其提示 。 不幸的是,每个语言文件都以一种不到司法鉴定的方式注释了相同的对话和/或屏幕文本,这意味着条目在各个国家之间并不一致,通常相差100-400毫秒。 时间码“开始”事件根本不同步。
文件定义对象
主文档容器是一个简单的标头,它提供有关文档的元数据以及有关视觉表示的信息(模板,各个样式)。
定时的叠加项将作为数组存储在data属性中。
{
“ id”:“ 33834784375375”,
“ title”:“肖申克的救赎”,
“ format”:“ SubRip”,
“模板”:{
“ default”:“ __CONTENT__”,
“斜体”:“ __ CONTENT __ ”
},
“样式”:{
“ default”:“字体样式:10px;行高:1;颜色:#FFF;”
},
“数据”:[]
}
重叠对象
屏幕事件是一组覆盖对象,按其开始时间码(以毫秒为单位)对ASC进行排序。
时间编码的字幕覆盖表示为常见的JSON对象:
- 触发器 :发生屏幕事件提示的时间(以毫秒为单位)。
- lang :要显示的内容的ISO语言代码。
- styles :播放设备应将哪些样式类应用于内容。
- 模板 :播放设备应将哪些显示模板应用于内容(排队)。
- start :屏幕事件触发时间的数学细分。
- end :屏幕事件应结束且不再显示的时间的数学细分。
- 持续时间 :屏幕事件生命周期的数学分解。
- content :应显示的LTR / RTL字符串。
- meta :任何可以添加到overlay事件中以使播放设备受益的自定义数据,
{
“触发器”:4736088,
“ lang”:“ en”,
“样式”:[
“默认”
],
“模板”:[
“默认”
],
“开始”:{
“时间”:4736088,
“小时”:1
“分钟”:18,
“秒”:56
“毫秒”:88
},
“结束”: {
“时间”:4739256,
“小时”:1
“分钟”:18,
“秒”:59,
“ ms”:256
},
“持续时间”:{
“秒”:3.168,
“ ms”:3168
},
“ content”:“有一百种不同的方法可以使您脱颖而出。”,
“元”:{
“原版的”: {
“ start”:“ 01:18:56,088”,
“ end”:“ 01:18:59,256”
}
}
}
用Java显示
假设我们在显示环境中有JQuery的示例(例如,基于节点的程序(如Electron)或网络播放器(如Video.js)。
从EN字幕文件中提取所有字幕并将其打印到有序HTML列表的示例:
$(video_player_object).load(function(){
$ .getJSON(“ subtitles / zh-CN / RAW_en_the_shawshank_redemption.json”,function(file_contents){
var items = [];
$ .each(file_contents.data,function(key,val){
items.push(“
});
$(“
“ class”:“ my-new-list”,
html:items.join(“”)
})。appendTo(“ body”);
});
});
从具有EN,FR,PT和IT条目的多语言文件中提取所有西班牙语覆盖数据的示例。
$(video_player_object).load(function(){
$ .getJSON(“字幕/多语言/RAW_multi_the_shawshank_redemption.json”,function(file_contents){
var items = [];
$ .each(file_contents.data,function(key,val){
call_some_function_when_time_hits(val.trigger,val.content);
//等
});
});
});
在NoSQL存储中搜索
一旦存储在后端NoSQL数据库(如MongoDB,CouchDB,Neo4j甚至HTML5 localStorage)中,我们突然就有了一种搜索电影的方法。
用MongoDB查询
从多语言字幕文件中获取所有FR字幕
(假设我们已经知道文档ID为4ecc05e55dd98a436ddcc47c )。
db.subtitles.find({“ _ id”:ObjectId(“ 4ecc05e55dd98a436ddcc47c”),'data.lang':'fr'})
电影何时提到“脱脂”一词?
db.subtitles.ensureIndex({content:1});
db.subtitles.find(content:“ skim”);
字幕显示的平均持续时间是多少?
db.subtitles.find({“ _ id”:ObjectId(“ 4ecc05e55dd98a436ddcc47c”)})。aggregate(
[
{
$ group:
{
_id:“ $ item”,
avgDuration:{$ avg:“ $ duration”}
}
}
]
)
有人说“操”多少次?
使用Mongo的MapReduce
功能(https://docs.mongodb.com/manual/core/map-reduce/)查看所有出现的关键字:
db.subtitles.mapReduce(map,reduce,{out:“ word_count”})
结果示例:
db.word_count.find()。sort({value:-1})
{“ _id”:“是”,“值”:3}
{“ _id”:“坏”,“值”:2}
{“ _id”:“好”,“值”:2}
{“ _id”:“ this”,“ value”:2}
{“ _id”:“都不”,“值”:1}
{“ _id”:“ or”,“ value”:1}
{“ _id”:“ something”,“ value”:1}
{“ _id”:“ that”,“ value”:1}
SubJSON在Attribution-ShareAlike(CC BY-SA)创用CC许可下可在Github上使用,任何人均可自由使用。
https://github.com/azcoppen/subtitle-json