LEADTOOLS合并来自不同来源的视频和音频 - Windows C++
本教程介绍如何使用LEADTOOLS 多媒体 SDK创建 Windows C++ 应用程序,该应用程序使用ltmmConvert控件和其他 LEADTOOLS 对象将来自不同文件的视频和音频合并为一个输出文件。
合并来自不同来源的视频和音频 - Windows C++
本教程介绍如何使用LEADTOOLS 多媒体 SDK创建 Windows C++ 应用程序,该应用程序使用ltmmConvert控件和其他 LEADTOOLS 对象将来自不同文件的视频和音频合并为一个输出文件。
| 概述 | |
|---|---|
| 概括 | 本教程介绍如何使用 LEADTOOLS 多媒体 SDK 将音频和视频合并为一个文件。 |
| 完成时间 | 30分钟 |
| Visual Studio 项目 | 下载教程项目 (19 KB) |
| 平台 | Windows API C++ 应用程序 |
| 集成开发环境 | Visual Studio 2019 |
| 开发许可证 | 下载 LEADTOOLS |
| 尝试使用其他语言 |
|

所需知识
在开始“从不同来源合并视频和音频 - Windows C++”教程之前,请先完成“添加引用”和“设置许可证”教程。
创建项目并添加多媒体头文件和 LIB 文件
从“添加引用”和“设置许可证”教程中创建的 64 位 Windows API 项目的副本开始。 Start with a copy of the 64-bit Windows API project created in the Add References and Set a License tutorial. 如果该项目不可用,请按照该教程中的步骤创建它。
为了使用该ltmmConvert对象,LEADTOOLS 需要额外的引用。通过打开预编译头文件(取决于所使用的 Visual Studio 版本)添加所需的多媒体库引用pch.h,stdafx.h并添加以下几行:
// Add LEADTOOLS Multimedia reference
#include "C:\LEADTOOLS23\Include\ltmm.h"
#include "C:\LEADTOOLS23\Include\ltmm_Errors.h"
//x64 libs
#pragma comment (lib, "C:\\LEADTOOLS23\\Lib\\CDLL\\x64\\Ltmmx.lib")
#pragma comment (lib, "C:\\LEADTOOLS23\\Lib\\CDLL\\x64\\ltmmuuidx.lib")
添加代码以合并媒体文件
创建项目、添加参考并设置许可证后,就可以开始编码了。
在项目的主 CPP 文件中,找到该InitInstance()函数并在开头添加以下代码行,以初始化 Windows COM 库。
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
CoInitialize(NULL);
// Keep the rest of the function unchanged
以下步骤适用于 Visual Studio 2019;对于其他版本的 Visual Studio,它们可能有所不同。
前往解决方案资源管理器,双击资源文件 (.rc)。展开资源树中的菜单选项卡,然后双击菜单资源以在设计器界面中打开它。在“Exit ”项下方的空白处,单击并输入“&Merge Audio and Video”。将新项拖到“Exit”上方。确保该项的 ID 为ID_FILE_MERGEAUDIOANDVIDEO。
前往项目的主 CPP 文件,其中包含WndProc()主窗口函数。找到switch (wmId)该 case 下方的语句WM_COMMAND,并添加如下所示的新 case。
// In WndProc(), under "case WM_COMMAND:"
switch (wmId)
{
case ID_FILE_MERGEAUDIOANDVIDEO:
if(FAILED(CombineAudioandVideo()))
MessageBox(hWnd, TEXT("Combining failed"), TEXT("LEADTOOLS Demo"), MB_ICONERROR);
else
MessageBox(NULL, TEXT("Combining successful"), TEXT("LEADTOOLS Demo"), MB_ICONINFORMATION);
break;
// Keep rest of the code as is
下面是代码中使用的SelectCompressor()、CombineFiles()和函数的代码。CombineAudioandVideo()
要测试,请使用以下示例文件:
选择压缩机(IltmmCompressors *pCompressors,const TCHAR *pszCompressorName)
void SelectCompressor(IltmmCompressors *pCompressors, const TCHAR *pszCompressorName)
{
long index;
BSTR bstrCompressorName = SysAllocString(pszCompressorName);
pCompressors->Find(bstrCompressorName, &index);
pCompressors->put_Selection(index);
SysFreeString(bstrCompressorName);
}
合并文件(IltmmSampleTarget* pVideoTarget、IltmmSampleTarget* pAudioTarget、const TCHAR* _targetFile)
HRESULT CombineFiles(IltmmSampleTarget* pVideoTarget, IltmmSampleTarget* pAudioTarget, const TCHAR* _targetFile)
{
IltmmMultiStreamSource* pMSSource = NULL;
HRESULT hr = CoCreateInstance(CLSID_ltmmMultiStreamSource, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMultiStreamSource, (void**)&pMSSource);
if (FAILED(hr))
return hr;
pMSSource->put_StreamCount(2);
IltmmMediaTypeDisp* pmt = NULL;
hr = pVideoTarget->GetConnectedMediaType(&pmt);
if (FAILED(hr))
return hr;
hr = pMSSource->SetMediaType(0, pmt);
if (FAILED(hr))
return hr;
pmt->Release();
pmt = NULL;
hr = pAudioTarget->GetConnectedMediaType(&pmt);
if (FAILED(hr))
return hr;
hr = pMSSource->SetMediaType(1, pmt);
if (FAILED(hr))
return hr;
pmt->Release();
pmt = NULL;
IltmmConvert* pCombineConvert = NULL;
hr = CoCreateInstance(CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, IID_IltmmConvert, (void**)&pCombineConvert);
if (FAILED(hr))
return hr;
pCombineConvert->put_SourceObject(pMSSource);
BSTR bstrTargetFile = SysAllocString(_targetFile);
pCombineConvert->put_TargetFile(bstrTargetFile);
SysFreeString(bstrTargetFile);
//Select the desired compressor based on the name
#define LEAD_H264_ENCODER L"@device:sw:{33D9A760-90C8-11D0-BD43-00A0C911CE86}\\LEAD H264 Encoder (4.0)"
#define LEAD_AAC_AUDIO_ENCODER L"@device:sw:{33D9A761-90C8-11D0-BD43-00A0C911CE86}\\{E2B7DD70-38C5-11D5-91F6-00104BDB8FF9}"
//Set the Video Compressor
IltmmCompressors* pCompressors;
pCombineConvert->get_VideoCompressors(&pCompressors);
SelectCompressor(pCompressors, LEAD_H264_ENCODER);
pCompressors->Release();
//Set the Audio Compressor
pCombineConvert->get_AudioCompressors(&pCompressors);
SelectCompressor(pCompressors, LEAD_AAC_AUDIO_ENCODER);
pCompressors->Release();
pCombineConvert->put_TargetFormat(ltmmConvert_TargetFormat_MPEG2_TRANSPORT);
IltmmMediaSampleDisp* pmsSrc = NULL;
IltmmMediaSampleDisp* pmsDst = NULL;
long lStartTimeHi;
long lStartTimeLo;
long lStopTimeHi;
long lStopTimeLo;
VARIANT vBuffer;
VARIANT_BOOL vBool;
long lActualDataLength;
//Begin the running the Combine ConvertCtrl
pCombineConvert->StartConvert();
//Video Write
while (true)
{
pVideoTarget->GetSample(10000, &pmsSrc);
if (!pmsSrc)
break;
// get a source sample
hr = pMSSource->GetSampleBuffer(0, 10000, &pmsDst);
if (FAILED(hr))
break;
// copy the data to the source sample
hr = pmsSrc->get_Buffer(&vBuffer);
if (FAILED(hr))
break;
hr = pmsSrc->get_ActualDataLength(&lActualDataLength);
if (FAILED(hr))
break;
hr = pmsDst->SetData(lActualDataLength, vBuffer);
if (FAILED(hr))
break;
// copy the sample time
hr = pmsSrc->GetTime(&lStartTimeHi, &lStartTimeLo, &lStopTimeHi, &lStopTimeLo);
if (FAILED(hr))
pmsDst->ResetTime();
else
{
hr = pmsDst->SetTime(lStartTimeHi, lStartTimeLo, lStopTimeHi, lStopTimeLo);
if (FAILED(hr))
break;
}
// copy the other flags
hr = pmsSrc->get_Discontinuity(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_Discontinuity(vBool);
if (FAILED(hr))
break;
hr = pmsSrc->get_Preroll(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_Preroll(vBool);
if (FAILED(hr))
break;
hr = pmsSrc->get_SyncPoint(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_SyncPoint(vBool);
if (FAILED(hr))
break;
//release the source sample
pmsSrc->Release();
pmsSrc = NULL;
// deliver the source sample
hr = pMSSource->DeliverSample(0, 2000, pmsDst);
if (FAILED(hr))
break;
// release the source sample
pmsDst->Release();
pmsDst = NULL;
}
//Audio Write
while (true)
{
pAudioTarget->GetSample(10000, &pmsSrc);
if (!pmsSrc)
break;
// get a source sample
hr = pMSSource->GetSampleBuffer(1, 10000, &pmsDst);
if (FAILED(hr))
break;
// copy the data to the source sample
hr = pmsSrc->get_Buffer(&vBuffer);
if (FAILED(hr))
break;
hr = pmsSrc->get_ActualDataLength(&lActualDataLength);
if (FAILED(hr))
break;
hr = pmsDst->SetData(lActualDataLength, vBuffer);
if (FAILED(hr))
break;
// copy the sample time
hr = pmsSrc->GetTime(&lStartTimeHi, &lStartTimeLo, &lStopTimeHi, &lStopTimeLo);
if (FAILED(hr))
pmsDst->ResetTime();
else
{
hr = pmsDst->SetTime(lStartTimeHi, lStartTimeLo, lStopTimeHi, lStopTimeLo);
if (FAILED(hr))
break;
}
// copy the other flags
hr = pmsSrc->get_Discontinuity(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_Discontinuity(vBool);
if (FAILED(hr))
break;
hr = pmsSrc->get_Preroll(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_Preroll(vBool);
if (FAILED(hr))
break;
hr = pmsSrc->get_SyncPoint(&vBool);
if (FAILED(hr))
break;
hr = pmsDst->put_SyncPoint(vBool);
if (FAILED(hr))
break;
//release the source sample
pmsSrc->Release();
pmsSrc = NULL;
// deliver the source sample
hr = pMSSource->DeliverSample(1, 2000, pmsDst);
if (FAILED(hr))
break;
// release the source sample
pmsDst->Release();
pmsDst = NULL;
}
pCombineConvert->StopConvert();
pMSSource->DeliverEndOfStream(0, 1000);
pMSSource->DeliverEndOfStream(1, 1000);
pCombineConvert->ResetSource();
pMSSource->Release();
pCombineConvert->Release();
return hr;
}
合并音频和视频()
int CombineAudioandVideo()
{
// Initialize the convert control
IltmmConvert *pVidConvert = NULL, *pAudConvert = NULL;
HRESULT hr = CoCreateInstance(CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, IID_IltmmConvert, (void**)&pVidConvert);
if (FAILED(hr))
return hr;
hr = CoCreateInstance(CLSID_ltmmConvert, NULL, CLSCTX_INPROC_SERVER, IID_IltmmConvert, (void**)&pAudConvert);
if (FAILED(hr))
return hr;
//Init the SampleTargets. The Video and Audio data from our files will write to these.
IltmmSampleTarget *pVidTarget = NULL, *pAudTarget = NULL;
hr = CoCreateInstance(CLSID_ltmmSampleTarget, NULL, CLSCTX_INPROC_SERVER, IID_IltmmSampleTarget, (void**)&pVidTarget);
if (FAILED(hr))
return hr;
hr = CoCreateInstance(CLSID_ltmmSampleTarget, NULL, CLSCTX_INPROC_SERVER, IID_IltmmSampleTarget, (void**)&pAudTarget);
if (FAILED(hr))
return hr;
IltmmMediaTypeDisp* pmt = NULL;
hr = CoCreateInstance(CLSID_ltmmMediaType, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMediaTypeDisp, (void**)&pmt);
if (FAILED(hr))
return hr;
pmt->put_Type((BSTR)ltmmMEDIATYPE_Video);
// make the SampleTarget object accept connections of this media type
hr = pVidTarget->SetAcceptedMediaType(pmt);
if (FAILED(hr))
return hr;
pVidConvert->put_TargetObject(pVidTarget);
pmt->Release();
pmt = NULL;
hr = CoCreateInstance(CLSID_ltmmMediaType, NULL, CLSCTX_INPROC_SERVER, IID_IltmmMediaTypeDisp, (void**)&pmt);
if (FAILED(hr))
return hr;
pmt->put_Type((BSTR)ltmmMEDIATYPE_Audio);
// make the SampleTarget object accept connections of this media type
hr = pAudTarget->SetAcceptedMediaType(pmt);
if (FAILED(hr))
return hr;
pAudConvert->put_TargetObject(pAudTarget);
pmt->Release();
pmt = NULL;
// Ensure this is the correct path
BSTR bstrSourceFileVid = SysAllocString(TEXT("Video-Source.mp4"));
hr = pVidConvert->put_SourceFile(bstrSourceFileVid);
if (FAILED(hr))
return hr;
SysFreeString(bstrSourceFileVid);
// Ensure this is the correct path
BSTR bstrSourceFileAud = SysAllocString(TEXT("Audio-Source.mpg"));
hr = pAudConvert->put_SourceFile(bstrSourceFileAud);
if (FAILED(hr))
return hr;
SysFreeString(bstrSourceFileAud);
pVidConvert->StartConvert();
pAudConvert->StartConvert();
// Ensure this is the correct path
hr = CombineFiles(pVidTarget, pAudTarget, TEXT("Combined-File.mpg"));
long lState = 0;
pVidConvert->get_State(&lState);
if (lState == ltmmConvert_State::ltmmConvert_State_Running)
pVidConvert->StopConvert();
lState = 0;
pAudConvert->get_State(&lState);
if (lState == ltmmConvert_State::ltmmConvert_State_Running)
pAudConvert->StopConvert();
pVidTarget->Release();
pVidTarget = NULL;
pAudTarget->Release();
pAudTarget = NULL;
pAudConvert->Release();
pVidConvert->Release();
return hr;
}
运行项目
按F5或选择“调试”->“开始调试”来运行项目。
如果正确遵循这些步骤,应用程序将运行并将音频和视频源文件转换为一个媒体文件。如果使用了上面的示例文件,这将是预期的输出媒体文件。
本教程展示了如何使用ltmmConvertObject 将两个媒体文件(一个视频和一个音频)合并为一个文件。
参见
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)