因爲原公司一哥們,想要把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 安裝目錄下有幫助文檔對命令行進行詳細說明:
最後,下載資源參加下面的資源連接