qt实现播放视屏的时候,加载外挂字幕(.srt文件解析)

之前用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