赞
踩
有时候人们能够下载一些感兴趣的视频但是发现并没有字幕,到字幕网站上查找到字幕文件,但是发现时间进度上不能完美配合,一个视频数据的例子来源于链接:
BBC.巴塔哥尼亚:地球秘密乐园 https://www.aliyundrive.com/s/LmF2sgrQzMu/folder/612af030c6fa4bf4b7cf498d96acda7b9ef9258e
相应的字幕文件来自于链接:
https://so.zimuku.org/search?q=%E5%9C%B0%E7%90%83%E7%A7%98%E5%AF%86%E4%B9%90%E5%9B%AD&chost=zimuku.org
上述视频和字幕文件在时间进度上不能完美匹配。
字幕文件内容由以下示例段落组成,具体可下载文件后查看:
1
00:00:04,480 --> 00:00:07,120
In a far corner of the Earth
在地球的另一个角落
2
00:00:07,120 --> 00:00:10,560
is a South American wilderness.
是南美洲的荒野.
注意字幕文件的名字需要与对应的视频文件名一致,不包括扩展名。
通常来说,各段字幕之间的间隔是准确的,如果有一个软件可以把字幕文件中的各个段落统一提前或推迟相同的时间,调整几次后就可以生成与视频进度完美匹配的字幕文件。
设计一个类Subtitle代表一段字幕,其成员包括int id,两个时间类对象startTime和endTime(时间类应该有函数支持加减一个时间常量的运算),一个vect<string>对象代表着一条或多条字幕内容(如果是双语则有两行字符串,单一语言则只有一行),一个类Video代表视频,Video中有一个指针pst指向系列Subtitle对象,有一个成员函数readSubtitle从文件中读取所有字幕,有一个函数adjustSubtitle调整所有字幕的时间点,有一个函数writeSubtitle将所有字幕内容定稿字幕文件。主函数中生成一个Video对象,通过该类的成员函数读取字幕文件、修改时间进度并将修改后的字幕内容保存以供测试。
文件操作需要#include <fstream>
ifstream myfile("巴塔哥尼亚.E01.srt"); //打开文件读
myfile >> myvar; //可以像cin一样从文件中读数据到变量
string s;
getline(myfile, s); //从myfile中读取一整行到变量s
myfile.close(); //同一文件只有关闭后才能再打开写
//写文件
ofstream outfile("巴塔哥尼亚.E01.srt"); //打开文件写
和cout一样操作outfile,写完后close,就可以保存文件。
函数writeSubtitle将所有字幕内容保存到字幕文件
pst也可以考虑用vector更方便,每发现一个字幕,push_back到数组中
我们首先要打开我们需要打开的文件
我们首先来创建一个类Video和Subtitle来存储相应的数据,我们通过观察字幕的文件发现其文件的特征
- class Subtitle
- {
- private:
- int id;
- Time startTime, endTime;//字幕的开始时间和结束时间
- vector<string> lines;//表示字幕的内容
- public:
- Subtitle(int id, const Time& start, const Time& end, const vector<string>& lines)
- : id(id), startTime(start), endTime(end), lines(lines)
- {}
- void adjust(int ms)//调整字幕的开始时间和结束时间
- {
- startTime.adjust(ms);
- endTime.adjust(ms);
- }
- string toString() const//将字幕的信息转换为字符串格式
- {
- ostringstream oss;
- oss << id << "\n";
- oss << startTime.toString() << " --> " << endTime.toString() << "\n";//将字幕的开始时间和结束时间输出到oss中
- for (const string& line : lines)//历字幕的每一行,将其输出到 oss 中,然后输出一个换行符。
- {
- oss << line << "\n";
- }
- oss << "\n";
- return oss.str();//将oss中的数据转换为字符串,并返回
- }
- };
- bool isNumber(const string& str)
- {
- return !str.empty() && all_of(str.begin(), str.end(),
- [](unsigned char c)//C++ 的 all_of 算法,检查 str 中的所有字符。接受一个字符 c,并检查 c 是否是数字。
- { return ::isdigit(c); });//isdigit用于检查一个字符是否是数字
- }
- class Video
- {
- private:
- string subtitleFile;
- vector<Subtitle> subtitles;//存储多个时间加后面的字幕
- void readSubtitles()//从字幕文件中读取字幕
- {
- //判断是否打开
- ifstream infile(subtitleFile);
- if (!inf
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。