我的博客中讲述过WMS9,可以实现流媒体服务器,但没有WME(windows media encoder)的支持,总觉得缺少点什么,这里就讲述一下如何通过.net实现WME获取设备视频音频流,并推送到远程(本地当然可以)流媒体广播发布点。
一.下载了wme9的SDK,安装完毕:这一步主要体验一下WME能够实现那些功能。
读者可以自行安装试试。
二.创建.net winform Application,添加引用
using WMEncoderLib;
WMEncoderLib是一个assemble,通过它,我们可以方便实现WME的操作。
三.获取本地屏幕,并转换为视频信号
IWMEncSource SrcAud = SrcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO); IWMEncSource SrcVid = SrcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO); SrcAud.SetInput( " Default_Audio_Device " , " Device " , "" ); SrcVid.SetInput( " ScreenCapture1 " , " ScreenCap " , "" );
四.启动Encoder,推送到远程WMS服务器
// Set up the push broadcast. IWMEncPushDistribution PushDist = (IWMEncPushDistribution)Encoder.Broadcast; string strServerName = this .TB_ServerName.Text.Trim() + " : " + this .TB_Port.Text.Trim(); string strPubPoint = " TmpBroadCastPubPoint " ; // Remove the publishing point when the broadcast is over. PushDist.AutoRemovePublishingPoint = true ; // Set the push distribution variables. PushDist.ServerName = strServerName; PushDist.PublishingPoint = strPubPoint; // PushDist.Template = strPubTemplate; // Initialize the encoding process. Encoder.PrepareToEncode( true );
注意:在这里,直接推送到远程服务器,如果服务器不在同一域内,或在不可信任区域,推送时应该会需要验证用户名和密码。因此我们需要创建一个委托:
Encoder.OnAcquireCredentials += new _IWMEncoderEvents_OnAcquireCredentialsEventHandler(OnUserAuth); public void OnUserAuth( string bstrRealm, string bstrSite, ref object pvarUser, ref object pvarPassword, ref object plFlags) ... { pvarUser = " administrator " ; pvarPassword = " 622316 " ; plFlags = 4 ; }
五.到这里就差不多了,完整代码贴出来:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using WMEncoderLib; namespace Project2 ... { public partial class Form1 : Form ... { static bool bDone; private WMEncoder Encoder; public Form1() ... { InitializeComponent(); Encoder = new WMEncoder(); Encoder.OnStateChange += new _IWMEncoderEvents_OnStateChangeEventHandler(OnWmeStatusChange); Encoder.OnError += new _IWMEncoderEvents_OnErrorEventHandler(Encoder_OnError); Encoder.OnAcquireCredentials += new _IWMEncoderEvents_OnAcquireCredentialsEventHandler(OnUserAuth); } private void Btn_Start_Click( object sender, EventArgs e) ... { this .StartBroadCast(); } private void Btn_Close_Click( object sender, EventArgs e) ... { this .StopBroadCast(); } /**/ /// <summary> /// 停止广播服务 /// </summary> public void StopBroadCast() ... { this .Encoder.Stop(); } /**/ /// <summary> /// 启动广播服务 /// </summary> public void StartBroadCast() ... { if (Encoder != null ) ... { // Retrieve the source group collection. IWMEncSourceGroupCollection SrcGrpColl = Encoder.SourceGroupCollection; // Add a source group to the collection. IWMEncSourceGroup SrcGrp = SrcGrpColl.Add( " SG_2 " ); IWMEncSource SrcAud = SrcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO); IWMEncSource SrcVid = SrcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO); SrcAud.SetInput( " Default_Audio_Device " , " Device " , "" ); SrcVid.SetInput( " ScreenCapture1 " , " ScreenCap " , "" ); // Choose a profile from the collection. IWMEncProfileCollection ProColl = Encoder.ProfileCollection; IWMEncProfile Pro; for ( int i = 0 ; i < ProColl.Count; i ++ ) ... { Pro = ProColl.Item(i); if (Pro.Name == " Windows Media Video 8 for Local Area Network (384 Kbps) " ) ... { SrcGrp.set_Profile(Pro); break ; } } // Set up the push broadcast. IWMEncPushDistribution PushDist = (IWMEncPushDistribution)Encoder.Broadcast; // Specify the push distribution variables, including the Windows Media // server name, publishing point, and announcement files. string strServerName = this .TB_ServerName.Text.Trim() + " : " + this .TB_Port.Text.Trim(); string strPubPoint = " TmpBroadCastPubPoint " ; // string strPubTemplate = "AnotherPubPoint"; // string MyNSCFile = "//localhost/test/MyPubPoint.nsc"; // string MyNSCURL = "//localhost/MyPubPoint.nsc"; // string MyASXFile = @"C:InetpubwwwrootMyPubPoint.asx"; // Remove the publishing point when the broadcast is over. PushDist.AutoRemovePublishingPoint = true ; // Set the push distribution variables. PushDist.ServerName = strServerName; PushDist.PublishingPoint = strPubPoint; // PushDist.Template = strPubTemplate; // Initialize the encoding process. Encoder.PrepareToEncode( true ); // Generate the announcement file. // PushDist.GenerateMulticastInfoFile(MyNSCFile); // PushDist.GenerateAnnouncementFile(MyNSCURL, MyASXFile); // Start the encoding process. Encoder.Start(); // wmp.openPlayer("mms: // LIH-M/test"); this .wmp.URL = " mms://192.168.1.108/TmpBroadCastPubPoint " ; } } public void OnUserAuth( string bstrRealm, string bstrSite, ref object pvarUser, ref object pvarPassword, ref object plFlags) ... { pvarUser = " administrator " ; pvarPassword = " 622316 " ; plFlags = 4 ; } public void Encoder_OnError( int Result) ... { this .RTB_Error.Text = " 运行状态:出错代码 " + Result + " 【 " + Encoder.ErrorState.ToString() + " 】 " ; } public void OnWmeStatusChange(WMENC_ENCODER_STATE enumState) ... { switch (enumState) ... { case WMENC_ENCODER_STATE.WMENC_ENCODER_RUNNING: RTB_Error.Text += " 运行状态:Encoder正在运行 " ; break ; case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED: // TODO: Handle stopped state. bDone = true ; RTB_Error.Text += " 运行状态:Encoder已经停止 " ; break ; case WMENC_ENCODER_STATE.WMENC_ENCODER_STARTING: RTB_Error.Text += " 运行状态:Encoder正在启动 " ; break ; case WMENC_ENCODER_STATE.WMENC_ENCODER_PAUSING: // TODO: Handle pausing state. RTB_Error.Text += " 运行状态:Encoder正在暂停 " ; break ; case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPING: // TODO: Handle stopping state. RTB_Error.Text += " 运行状态:Encoder正在停止 " ; break ; case WMENC_ENCODER_STATE.WMENC_ENCODER_PAUSED: // TODO: Handle paused state. RTB_Error.Text += " 运行状态:Encoder已暂停 " ; break ; case WMENC_ENCODER_STATE.WMENC_ENCODER_END_PREPROCESS: // TODO: Handle end preprocess state. RTB_Error.Text += " 运行状态:Encoder正在处理结束前操作 " ; break ; } } } }
WME可以捕捉机器音频和视频等设备,如:摄像头,桌面,光驱,声卡,电视卡等等。因此我们可以通过它实现网上电视直播,视频、音频捕捉等等功能。有兴趣的话可以研究一下。