之前用qt写了一个在windows下播放视频的软件,具体介绍参见qt编写的视频播放器,windows下使用,精致小巧_GreenHandBruce的博客-CSDN博客
后来发现有些视频没有内嵌字幕,需要外挂字幕,这时候,我就想着把加载外挂字幕的功能加上。如下图:
这里先做了解析.srt字幕文件的功能。具体实现如下
1.先在窗口放一个label,将label调整到界面底部,设置字体,颜色
//显示字幕用的label;
labelSubTitle = new myLabel(this);
// labelSubTitle->setText("这里显示字幕文件");
QFont font("微软雅黑",15,QFont::Bold);
QPalette palette = labelSubTitle->palette();
palette.setColor(QPalette::WindowText,Qt::white);
labelSubTitle->setPalette(palette);
labelSubTitle->setFont(font);
labelSubTitle->setAlignment(Qt::AlignCenter);
2.在打开视频文件的时候找到同文件夹下的.srt文件
int nIndex = fileName.lastIndexOf('.');//寻找‘.’符号在字符串中的id
nIndex++;
QString srtfile =fileName.mid(0,nIndex); //截取‘.’符号后面的字符串,这是为了获取文件后缀名
srtfile +="srt";
EncodingFormat code = FileCharacterEncoding(srtfile);
QFile file(srtfile);
if(!file.open(QIODevice::ReadOnly)) {
qDebug()<<"未找到外挂字幕文件:"<<srtfile<<endl;
}
3.解析.srt文件,先看一下.srt字幕文件格式如下:
然后写个结构体用来存放解析之后的srt内容,如下:
struct SrtInfo
{
qint16 Num;
QTime dtStart;
QTime dtEnd;
QString strSubTitle;
};
然后解析,在解析的时候要注意.srt的编码格式,(编码格式这块参见我上一篇文章qt按照不同编码格式读取文字(UTF-16LE,UTF-8,UTF-8BOM,UTF-16BE)-CSDN博客)
void VideoPlayer::ParseSubTitle(QString fileName)
{
int nIndex = fileName.lastIndexOf('.');//寻找‘.’符号在字符串中的id
nIndex++;
QString srtfile =fileName.mid(0,nIndex); //截取‘.’符号后面的字符串,这是为了获取文件后缀名
srtfile +="srt";
EncodingFormat code = FileCharacterEncoding(srtfile);
QFile file(srtfile);
if(!file.open(QIODevice::ReadOnly)) {
qDebug()<<"未找到外挂字幕文件:"<<srtfile<<endl;
}
m_SrtInfoLst.clear();
QTextCodec::ConverterState state;
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
if(code==EncodingFormat::UTF16LE)
{
codec = QTextCodec::codecForName("UTF-16LE");
}
else if(code==EncodingFormat::UTF8)
{
codec = QTextCodec::codecForName("UTF-8");
}
else if(code==EncodingFormat::UTF8BOM)
{
codec = QTextCodec::codecForName("UTF-8");
}
else if(code==EncodingFormat::UTF16BE)
{
codec = QTextCodec::codecForName("UTF-16BE");
}
QTextStream stream_src(&file);
stream_src.setCodec(codec);
while(!stream_src.atEnd()) {
QString str = stream_src.readLine();
str = str.replace('\r',"");//替换回车符
str = str.replace('\n',"");//替换换行符
bool ok;
qint16 nID = str.toInt(&ok,10);
if(ok)
{
SrtInfo info;
info.Num = nID;
if(stream_src.atEnd())
break;
QString str2=stream_src.readLine();
str2 = str2.replace('\r',"");//替换回车符
str2 = str2.replace('\n',"");//替换换行符
str2 = str2.replace(' ',"");//替换空格符
if(str2=="")
continue;
info.dtStart = QTime::fromString(str2.split('-').first(),"hh:mm:ss,zzz");
info.dtEnd = QTime::fromString(str2.split('>').last(),"hh:mm:ss,zzz");
QString str3=stream_src.readLine();
if(str3=="")
continue;
str3 = str3.replace('\r',"");//替换回车符
str3 = str3.replace('\n',"");//替换换行符
info.strSubTitle = str3;
QString str4=stream_src.readLine();
if(str4=="")
continue;
str4 = str4.replace('\r',"");//替换回车符
str4 = str4.replace('\n',"");//替换换行符
info.strSubTitle.append('\n');
info.strSubTitle.append(str4);
m_SrtInfoLst.append(info);
}
}
file.close();
}
然后就是在播放视频的时候,找到当前时刻对应的字幕并显示在label上,如下:
void VideoPlayer::positionChanged(qint64 position)
{
m_positionSlider->setValue(position);
QTime timeCrt = QTime(0,0,0);
timeCrt = timeCrt.addMSecs(position);
QTime timeTotal =QTime(0,0,0);
timeTotal = timeTotal.addMSecs(m_mediaPlayer->duration());
QString str = timeCrt.toString("hh:mm:ss")+"/"+timeTotal.toString("hh:mm:ss");
// m_labelTiem->setFont(QFont::gra);
m_labelTiem->setText(str);
if(m_mediaPlayer->duration()>0&&position>=m_mediaPlayer->duration())
{
//图标变成play
QImage img;
img.load(":/play");
m_labelPlay->setPixmap(QPixmap::fromImage(img));
}
bool bShow = false;
foreach(const SrtInfo item,m_SrtInfoLst)
{
if(item.dtStart<timeCrt && item.dtEnd>timeCrt)
{
labelSubTitle->setText(item.strSubTitle);
bShow = true;
break;
}
}
if(!bShow)
{
labelSubTitle->setText("");
}
}
完整代码参见
https://download.csdn.net/download/weixin_43935474/88561361