因为原公司一哥们,想要把avi格式的视频文件转为wmv3编码规范的wmv视频,因为他是搞java的所以想让我帮着调查一下,然后我就答应了,然后我调查了一天发现真他妈的坑,网上几乎没有啥资料,这个wmEncoder也太古老了吧,编译还是vc6.0,操作系统还是xp,win7还是优化后才支持,更无奈的是,官网所有资料都已下架,唯一搜到的到的资料不是要积分就是要会员,要么下载下来驴唇不对马嘴,尴尬的很,经过两天的纠结,终于把资料下载完成,终于搞定,下面介绍一下过程,防止大家走弯路,以备参考,文后会附上相关资料(重点是资料要下对)。
一、安装WMenCoder
- wmencoder.zip Windows Media Encoder SDK是基于wmencoder这个软件的SDK(32位,64位根据需求下载),所以你必须安装这个软件才能进行二次开发,在win10上安装,一致弹出如下的错误:
因为这个东西实在太古老了,古老到没有人维护了,最好的办法解决就是解压这个exe文件,解压后你会得到一个msi文件,通过这个文件进行安装,如下图
安装成功后,你就会在开始菜单中看到windows media一栏,打开下面的Windows Media Encoder x64 Edition程序,就可以进行相关操作了,如下图:
想一下,其实因为是二次开发,所以基本上这个软件能做的事情,二次开发都可以搞定。所以有什么需求的话就可以先看看这个软件能不能满足,能够满足就可以接下来进行二次开发了。
调查发现此软件转化avi视频为wmv3格式文件,很轻松就完成了,ok!调查完毕,基础环境搭建完成,接下来就是要调查如何进行二次开发编码了。
二、安装WMenCoder SDK
WMEncoderSDK.exe,毋庸置疑安装了SDK才能进行代码开发,同样的在win10上直接运行exe文件,安装失败,还是需要通过解压得到msi文件进行安装,安装成功后,就可以创建编码工程了,以C++为例。
- 创建vs2015工程(vs版本都可以),自己喜欢的工程类型,控制台或对话框的mfc无所谓,测试下我喜欢用mfc的基于对话框的程序,在工程中添加引用头文件目录,如下图所示:
2.接下来就可以编码了,包含头文件#include <wmencode.h>,将c盘下a'vi文件转为wmv文件,主函数代码如下:
include <windows.h>
#include <wchar.h>
#include <atlbase.h>
#include "wmencode.h"
void Encoderfun()
{
// Declare variables.
HRESULT hr;
IWMEncoder* pEncoder;
IWMEncSourceGroupCollection* pSrcGrpColl;
IWMEncSourceGroup* pSrcGrp;
IWMEncSource* pAudSrc;
IWMEncSource* pVidSrc;
IWMEncProfileCollection* pProColl;
IWMEncProfile* pPro;
IWMEncFile* pFile;
long lCount;
int i;
// Initialize the COM library and retrieve a pointer
// to an IWMEncoder interface.
hr = CoInitialize(NULL);
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_WMEncoder,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWMEncoder,
(void**)&pEncoder);
}
// Retrieve a pointer to an IWMEncSourceGroupCollection
// interface.
if (SUCCEEDED(hr))
{
hr = pEncoder->get_SourceGroupCollection(&pSrcGrpColl);
}
// Add an empty source group to the collection.
if (SUCCEEDED(hr))
{
hr = pSrcGrpColl->Add(CComBSTR("SG_1"), &pSrcGrp);
}
// Add an audio and a video source to the source group.
if (SUCCEEDED(hr))
{
hr = pSrcGrp->AddSource(WMENC_AUDIO, &pAudSrc);
}
if (SUCCEEDED(hr))
{
hr = pSrcGrp->AddSource(WMENC_VIDEO, &pVidSrc);
}
// Retrieve a pointer to an IWMEncFile interface.
if (SUCCEEDED(hr))
{
hr = pEncoder->get_File(&pFile);
}
// Specify an .avi source file and a Windows Media file with a .wmv extension for the output.
CComBSTR m_bstrInFile("C:\\input.avi");
CComBSTR m_bstrOutFile("C:\\output.wmv");
if (SUCCEEDED(hr))
{
hr = pAudSrc->SetInput(m_bstrInFile);
}
if (SUCCEEDED(hr))
{
hr = pVidSrc->SetInput(m_bstrInFile);
}
if (SUCCEEDED(hr))
{
hr = pFile->put_LocalFileName(m_bstrOutFile);
}
// Retrieve the name of the output file.
CComBSTR m_bstrFileName(" ");
if (SUCCEEDED(hr))
{
hr = pFile->get_LocalFileName(&m_bstrFileName);
}
// Loop through the profile collection and retrieve a specific
// profile. You can find the profile name in the Profile Manager.
if (SUCCEEDED(hr))
{
hr = pEncoder->get_ProfileCollection(&pProColl);
}
CComBSTR m_bstrName(" ");
CComVariant m_varProfile;
m_varProfile.vt = VT_DISPATCH;
if (SUCCEEDED(hr))
{
hr = pProColl->get_Count(&lCount);
}
for (i = 0; i < lCount; i++)
{
if (SUCCEEDED(hr))
{
hr = pProColl->Item(i, &pPro);
}
if (SUCCEEDED(hr))
{
hr = pPro->get_Name(&m_bstrName);
}
if (_wcsicmp(m_bstrName, CComBSTR("profile_name")) == 0)
{
m_varProfile.pdispVal = pPro;
if (SUCCEEDED(hr))
{
hr = pSrcGrp->put_Profile(m_varProfile);
}
break;
}
}
// Start archiving when the encoding process starts. This is the default.
if (SUCCEEDED(hr))
{
hr = pEncoder->put_EnableAutoArchive(VARIANT_TRUE);
}
// Initialize and start the encoding process.
if (SUCCEEDED(hr))
{
hr = pEncoder->PrepareToEncode(VARIANT_TRUE);
}
if (SUCCEEDED(hr))
{
hr = pEncoder->Start();
}
// To determine when the encoding and archiving process has ended,
// you must implement the OnArchiveStateChange event in the
// _IWMEncoderEvents interface.
// Release pointers.
if (pEncoder)
{
pEncoder->Release();
pEncoder = NULL;
}
if (pSrcGrpColl)
{
pSrcGrpColl->Release();
pSrcGrpColl = NULL;
}
if (pSrcGrp)
{
pSrcGrp->Release();
pSrcGrp = NULL;
}
if (pAudSrc)
{
pAudSrc->Release();
pAudSrc = NULL;
}
if (pVidSrc)
{
pVidSrc->Release();
pVidSrc = NULL;
}
if (pProColl)
{
pProColl->Release();
pProColl = NULL;
}
if (pPro)
{
pPro->Release();
pPro = NULL;
}
if (pFile)
{
pFile->Release();
pFile = NULL;
}
}
编译成功,然后运行调试,发现每次都获取COM组件失败,坑人吧,在网上搜了一通,猜测是安装方式导致COM组件没有注册成功,具体怎么才能在win10 上注册成功,这个就没有继续调查,还是乖乖的在win7下搞,比较太久远了。至此就完成了这个需求。
三、脚本调用
等等,好像他的需求只是转格式文件而已, 干嘛非要用c++写程序呢,难道用脚本实现不香吗?很明显他的业务就是在服务器后端将格式转化成WMV格式,然后供前端下载或播放,你就算写个二次开发程序估计也是以脚本的形式调用,那就看看脚本功能支不支持,有没有很强大,结果发现,脚本功能很强大,基本功能就无需这个二次开发插件,一句话就完成了转化:
cscript.exe wmcmd.vbs –input C:\My-clips\Myfile.avi -output C:\My-clips-coded\Myfile.wmv
最后,我把命令行告诉了他,然后果然很香,以后再也不用二次开发了,直接用命令行就妥妥的,毕竟这种古老的格式,谁还会有那么多需求呢。在ENCODER 安装目录下有帮助文档对命令行进行详细说明:
最后,下载资源参加下面的资源连接