前一节已经实现了录制,只能录制一段视频,实际运用中我们可能会暂停,然后接着录制最终生成一条完整的视频。
我们在使用命令行操作ffmpeg时组合各段视频的命令如下:
ffmpeg -f conccat -safe 0 -i conccatfile -c copy dirfile
所以我的方法是暂停录制后生成一条临时视频,并把临时视频的文件名保存在conccatfile里面。重新开始录制又重新录制一条临时视频,这样如果一直反复暂停录制开始录制,会生成多个临时文件。停止录制时将这些视频组合成一条视频,从而完成录制的各种操作实现。
1.创建一个保存临时视频的文件
文件按录制开始的本地时间命名如下:
QString path = QString("%1/%2_tmp").arg(m_cacheDir).arg(QDateTime::currentDateTime().toMSecsSinceEpoch());
m_pConcatFile = new QFile(path);
if (!m_pConcatFile->open(QIODevice::ReadWrite | QIODevice::Text|QIODevice::Truncate))
qDebug() << "File open error";
2.开始录制
之前是直接给出最终的录制文件名,这里为了实现暂停录制功能,开始录制时使用临时文件。并把临时视频文件内容写入步骤1创建的文件
QString tmpFilePath = QString("v%1_tmp").arg(QDateTime::currentDateTime().toMSecsSinceEpoch());
QTextStream out(m_pConcatFile);
out << "file" << " '" << tmpFilePath << "'\n";
QString tmpFileAbsolutePath = m_cacheDir + "/"+ tmpFilePath;
args << tmpFileAbsolutePath; m_currentRecordTempFiles<<tmpFileAbsolutePath;
m_currentRecordTempFiles<<tmpFileAbsolutePath.replace("_tmp", ".mp4");
m_pRecordProcess->start("ffmpeg", args);
3.停止录制
新增加一个成员变量来判断时真的停止录制,如果时停止录制就开始组合视频。并将步骤1创建的组合文件列表的文件删除
m_bStopRecord = true;
m_concatFileName = m_pConcatFile->fileName();
m_pConcatFile->close();
m_pConcatFile->deleteLater();
m_pConcatFile = nullptr;
m_pRecordProcess->write("q");
4.暂停录制
暂停录制停止当前录制进程,并设置m_bStopRecord = false,这样就不会开始组合,下次开始录制会重新生成一个视频临时文件,并写入步骤1创建的组合文件列表的文件
m_bStopRecord = false;
m_pRecordProcess->write("q");
录制过程中会生成如下临时文件:
带v的表示视频,不带的表示组合文件列表:
5.组合录制视频
每次录制进程退出都会去判断m_bStopRecord = true,如果true则新建一个进程去处理视频组合。
connect(m_pRecordProcess, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[this](int exitCode, QProcess::ExitStatus exitStatus) {
if(!m_bStopRecord)
return;
QProcess* mergeProcess = new QProcess(this);
connect(mergeProcess, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[mergeProcess, this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug() << QStringLiteral("成功合成视频");
qDebug() << mergeProcess->readAllStandardError();
if(m_currentRecordTempFiles.count()>3)
m_currentVideoPath = m_currentRecordTempFiles.at(2);
clear();
});
if(m_currentRecordTempFiles.count()<3)
return ;
QStringList args;
args << "-f" << "concat";
args << "-safe" << "0";
args << "-i" << m_currentRecordTempFiles.at(0);
args << "-c" << "copy";
args << m_currentRecordTempFiles.at(2);
//合成视频
mergeProcess->start("ffmpeg", args);
————————————
其实就是对应上面写的那条命令。
组合后删除临时文件生成视频。
这样就能实现真正的录制场景。