字幕数据节点:
// 字幕数据节点定义
struct SSubtitleDataNode
{
__int64 nBeginTime;
__int64 nEndTime;
QString strText;
SSubtitleDataNode() {
nBeginTime = -1;
nEndTime = -1;
}
SSubtitleDataNode(__int64 nBegin, __int64 nEnd, const QString &str)
: nBeginTime(nBegin)
, nEndTime(nEnd)
, strText(str)
{
}
};
区分编码格式:
QString FindFileCode(const QString &fileName)
{
QFile file(fileName);
if (file.open(QIODevice::ReadOnly))
{
QByteArray buff = file.readLine();
QTextCodec::ConverterState state;
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QString text = codec->toUnicode(buff.constData(), buff.size(), &state);
if (state.invalidChars > 0)
return QString("GBK");
else
return QString("UTF8");
file.close();
}
return "GBK";
}
LRC文件解析:
QString strCodeType = FindFileCode(strPath);
__int64 nMediaDuration = -1;
// 读取文件
QFile file(strPath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QTextStream stream(&file);
stream.setCodec(strCodeType.toStdString().c_str()); //设置QTextStream对象的编码格式
QString readStr = stream.readAll();
file.close();
QRegularExpression rex("\\[(\\d+?:\\d+\\.\\d+)?\\]([^\r\n]*)"); // 正则表达式
QRegularExpressionMatch match = rex.match(readStr);
if (!match.hasMatch()) // 不支持本格式
return;
QRegularExpressionMatchIterator globalMatch = rex.globalMatch(readStr);
while (globalMatch.hasNext())
{
QRegularExpressionMatch item = globalMatch.next();
SSubtitleDataNode node;
for (int i = 0; i <= item.lastCapturedIndex(); i++)
{
auto strContent = item.captured(i);
if (strContent.isEmpty())
continue;
switch (i)
{
case 0: // 所有内容
break;
case 1: // 开始时间
{
QTime tBegin = QTime::fromString(strContent, "mm:ss.z");
if (tBegin.msec() == -1)
break;
node.nBeginTime = (tBegin.minute() * 60 + tBegin.second()) * 1000 + tBegin.msec();
}
break;
default: // 内容
{
if (!node.strText.isEmpty())
node.strText += "\n";
node.strText += strContent;
}
break;
}
}
if (node.strText.isEmpty() && !vecDatas.empty()) // 有些格式为第二行只有时间,为上一行的显示结束时间
vecDatas[vecDatas.size() - 1].nEndTime = node.nBeginTime;
else if (node.nBeginTime != -1)
vecDatas.push_back(node);
}
// 处理字幕结束时间,若是文件中未单独给出,则上一条字幕的结束时间为下下一条字幕的开始时间
for (int i = (int)vecDatas.size() - 1; i >= 0; i--)
{
if (vecDatas[i].nEndTime == -1)
{
if (i == (int)vecDatas.size() - 1)
vecDatas[i].nEndTime = vecDatas[i].nBeginTime + DEFAULT_ENDTEXT_DURATION;
else
vecDatas[i].nEndTime = vecDatas[i + 1].nBeginTime;
}
nMediaDuration = std::max(nMediaDuration, vecDatas[i].nEndTime);
}
SRT文件解析:
QString strCodeType = FindFileCode(strPath);
__int64 nMediaDuration = -1;
// 读取文件
QFile file(strPath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
QTextStream stream(&file);
stream.setCodec(strCodeType.toStdString().c_str()); //设置QTextStream对象的编码格式
QString readStr = stream.readAll();
file.close();
QRegularExpression rex("(\\d+)?\n(\\d+:\\d+:\\d+,\\d+) --> (\\d+:\\d+:\\d+,\\d+)(\\d*(?:\r?(?!\r?).*)*)\n(.*(?:\r?\n(?!\r?\n).*)*)"); // 正则表达式
QRegularExpressionMatch match = rex.match(readStr);
if (!match.hasMatch()) // 不支持本格式
return;
QRegularExpressionMatchIterator globalMatch = rex.globalMatch(readStr);
while (globalMatch.hasNext())
{
QRegularExpressionMatch item = globalMatch.next();
SSubtitleDataNode node;
for (int i = 0; i <= item.lastCapturedIndex(); i++)
{
auto strContent = item.captured(i);
if(strContent.isEmpty())
continue;
switch (i)
{
case 0: // 所有内容
break;
case 1: // 序号
break;
case 2: // 开始时间
{
QTime tBegin = QTime::fromString(strContent, "hh:mm:ss,zzz");
if (tBegin.msec() == -1)
break;
node.nBeginTime = (tBegin.hour() * 3600 + tBegin.minute() * 60 + tBegin.second()) * 1000 + tBegin.msec();
}
break;
case 3: // 结束时间
{
QTime tEnd = QTime::fromString(strContent, "hh:mm:ss,zzz");
if (tEnd.msec() == -1)
break;
node.nEndTime = (tEnd.hour() * 3600 + tEnd.minute() * 60 + tEnd.second()) * 1000 + tEnd.msec();
nMediaDuration = std::max(nMediaDuration, node.nEndTime);
}
break;
default: // 内容
{
if(!node.strText.isEmpty())
node.strText += "\n";
node.strText += strContent;
}
break;
}
}
if (node.nBeginTime != -1 && node.nEndTime != -1)
vecDatas.push_back(node);
}