微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Silverlight之视频录制

    

Silverlight之视频录制             

        分类:             Silverlight                   459人阅读     评论(1)     收藏     举报    

摘要:在前两篇Silverlight的文章中跟大家一块学习了Silverlight的基础知识、Silverlight摄像头麦克风的相关操作以及截图、声音录制等,在文章后面也简单的说明了为什么没有视频录制,今天就和大家一块看一下上一节中最后的一个问题:如何使用Silverlight进行视频录制。

主要内容

1.nesL项目简介

2.使用nesL实现视频录制

3.注意

一、nesL项目简介

在silverlight 中如何录制视频?相信这个问题有不少朋友都搜索过,但是好像目前还没有见到很好的答案,究其原因其实就是视频编码问题。当然也有朋友提到直接进行截图,只要每秒截取足够多的图片,然后依次播放就可以形成视频。但是我看到国外一个朋友使用此方法进行了几十秒的视频录制,其文件大小就达到了百兆级别,而且还进行了优化。因此这种方式要实现视频录制就目前而言还不是很合适。那么到底有没有好的方法呢?答案是有,但有限制,那就是借助于nesL。

Native Extensions for Silverlight(简称nesL)是由微软Silverlight团队进行开发,其目的主要为了增强Silverlight Out-of-browser离线应用的功能。大家都知道虽然Silverlight 4的OOB应用支持信任人权限提升功能,允许Silverlight的OOB应用对COM组件的访问,但对绝大多数Windows API仍旧无法调用,而nesL的出现正是为了解决这个问题。在最新的nesL 2.0中包含了大量有用的功能,而这其中就包括今天要说的视频编码部分。在nesL中有一个类库Microsoft.Silverlight.Windows.LocalEncode.dll主要负责本地视频和音频编码,这里就是用此类库来解决上面提到的视频录制问题。

二、使用nesL实现视频录制

在Microsoft.Silverlight.Windows.LocalEncode.dll中一个核心类就是EncodeSession,它负责音频和视频的编码输出工作。使用EncodeSession进行视频录制大概分为下面两步:

1.准备输入输出信息

在这个过程中需要定义VideInputFormatInfo、AudioInputFormatInfo、VideoOutputFormatInfo、AudioOutputFormatInfo和OutputContainerInfo,然后调用EncodeSession.Prepare()方法

2.捕获视频输出

当输入输出信息准备好之后接下来就是调用EncodeSession.Start()方法进行视频编码输出。当然为了接收音频和视频数据必须准备两个sink类,分别继承于AudioSink和Videosink,在这两个sink中指定CaptureSource,并且在对应的OnSample中调用EncodeSession的WirteVideoSample()和WirteAudioSample()接收并编码数据(关于AudioSink在前面的文章中已经说过,Videosink与之类似)。

知道了EncodeSession的使用方法后下面就将其操作进行简单封装,LocalCamera.cs是本例中的核心类:

  1. using System;  
  2. using System.Collections.ObjectModel;  
  3. using System.IO;  
  4. using System.Windows;  
  5. using System.Windows.Threading;  
  6. using System.Windows.Media;  
  7. using System.Windows.Controls;  
  8. using System.Windows.Shapes;  
  9. using Microsoft.Silverlight.Windows.LocalEncode;  
  10.   
  11. namespace Cmj.MyWeb.MySilverlight.SilverlightMeida  
  12. {  
  13.     /// <summary>  
  14.     /// 编码状态  
  15.     /// </summary>  
  16.     public enum EncodeSessionState  
  17.     {  
  18.         Start,  
  19.         Pause,  
  20.         Stop  
  21.     }  
  22.     /// <summary>  
  23.     /// 本地视频对象  
  24.     /// </summary>  
  25.     public class LocalCamera  
  26.     {  
  27.         private string _saveFullPath = "";  
  28.         private uint _videoWidth = 640;  
  29.         private uint _videoHeight = 480;  
  30.         private VideosinkExtensions _videosink = null;  
  31.         private AudioSinkExtensions _audioSink= null;  
  32.         private EncodeSession _encodeSession = null;  
  33.         private UserControl _page = null;  
  34.         private CaptureSource _cSource = null;  
  35.         public LocalCamera(UserControl page,VideoFormat videoFormat,AudioFormat audioFormat)  
  36.         {  
  37.             //this._saveFullPath = saveFullPath;  
  38.             this._videoWidth = (uint)videoFormat.PixelWidth;  
  39.             this._videoHeight = (uint)videoFormat.PixelHeight;  
  40.             this._page = page;  
  41.             this.SessionState = EncodeSessionState.Stop;  
  42.             //this._encodeSession = new EncodeSession();  
  43.             _cSource = new CaptureSource();  
  44.             this.VideoDevice = DefaultVideoDevice;  
  45.             this.VideoDevice.DesiredFormat = videoFormat;  
  46.             this.AudioDevice = DefaultAudioDevice;  
  47.             this.AudioDevice.DesiredFormat = audioFormat;  
  48.             _cSource.VideoCaptureDevice = this.VideoDevice;  
  49.             _cSource.AudioCaptureDevice = this.AudioDevice;  
  50.             audioInputFormatInfo = new AudioInputFormatInfo() { SourceCompressionType = FormatConstants.AudioFormat_PCM };  
  51.             videoInputFormatInfo = new VideoInputFormatInfo() { SourceCompressionType = FormatConstants.VideoFormat_ARGB32 };  
  52.             audioOutputFormatInfo = new AudioOutputFormatInfo() { TargetCompressionType = FormatConstants.AudioFormat_AAC };  
  53.             videoOutputFormatInfo = new VideoOutputFormatInfo() { TargetCompressionType = FormatConstants.VideoFormat_H264 };  
  54.             outputContainerInfo = new OutputContainerInfo() { ContainerType = FormatConstants.TranscodeContainerType_MPEG4 };  
  55.         }  
  56.   
  57.         public LocalCamera(UserControl page,VideoCaptureDevice videoCaptureDevice,AudioCaptureDevice audioCaptureDevice, VideoFormat videoFormat, AudioFormat audioFormat)  
  58.         {  
  59.             //this._saveFullPath = saveFullPath;  
  60.             this._videoWidth = (uint)videoFormat.PixelWidth;  
  61.             this._videoHeight = (uint)videoFormat.PixelHeight;  
  62.             this._page = page;  
  63.             this.SessionState = EncodeSessionState.Stop;  
  64.             //this._encodeSession = new EncodeSession();  
  65.             _cSource = new CaptureSource();  
  66.             this.VideoDevice = videoCaptureDevice;  
  67.             this.VideoDevice.DesiredFormat = videoFormat;  
  68.             this.AudioDevice = audioCaptureDevice;  
  69.             this.AudioDevice.DesiredFormat = audioFormat;  
  70.             _cSource.VideoCaptureDevice = this.VideoDevice;  
  71.             _cSource.AudioCaptureDevice = this.AudioDevice;  
  72.             audioInputFormatInfo = new AudioInputFormatInfo() { SourceCompressionType = FormatConstants.AudioFormat_PCM };  
  73.             videoInputFormatInfo = new VideoInputFormatInfo() { SourceCompressionType = FormatConstants.VideoFormat_ARGB32 };  
  74.             audioOutputFormatInfo = new AudioOutputFormatInfo() { TargetCompressionType = FormatConstants.AudioFormat_AAC };  
  75.             videoOutputFormatInfo = new VideoOutputFormatInfo() { TargetCompressionType = FormatConstants.VideoFormat_H264 };  
  76.             outputContainerInfo = new OutputContainerInfo() { ContainerType = FormatConstants.TranscodeContainerType_MPEG4 };  
  77.         }  
  78.   
  79.         public EncodeSessionState SessionState   
  80.         {  
  81.             get;  
  82.             set;  
  83.         }  
  84.         public EncodeSession Session  
  85.         {  
  86.             get  
  87.             {  
  88.                 return _encodeSession;  
  89.             }  
  90.             set  
  91.             {  
  92.                 _encodeSession = value;  
  93.             }  
  94.         }  
  95.         /// <summary>  
  96.         /// 编码对象所在用户控件对象  
  97.         /// </summary>  
  98.         public UserControl OwnPage  
  99.         {  
  100.             get  
  101.             {  
  102.                 return _page;  
  103.             }  
  104.             set  
  105.             {  
  106.                 _page = value;  
  107.             }  
  108.         }  
  109.         /// <summary>  
  110.         /// 捕获源  
  111.         /// </summary>  
  112.         public CaptureSource Source  
  113.         {  
  114.             get  
  115.             {  
  116.                 return _cSource;  
  117.             }  
  118.         }  
  119.         /// <summary>  
  120.         /// 操作音频对象  
  121.         /// </summary>  
  122.         public AudioSinkExtensions AudioSink  
  123.         {  
  124.             get  
  125.             {  
  126.                 return _audioSink;  
  127.             }  
  128.         }  
  129.   
  130.         public static VideoCaptureDevice DefaultVideoDevice  
  131.         {  
  132.             get  
  133.             {  
  134.                 return CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();  
  135.             }  
  136.         }  
  137.           
  138.         public static ReadOnlyCollection<VideoCaptureDevice> AvailableVideoDevice  
  139.         {  
  140.             get  
  141.             {  
  142.                 return CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices();  
  143.             }  
  144.         }  
  145.   
  146.         public VideoCaptureDevice VideoDevice  
  147.         {  
  148.             get;  
  149.             set;  
  150.         }  
  151.   
  152.         public static AudioCaptureDevice DefaultAudioDevice  
  153.         {  
  154.             get  
  155.             {  
  156.                 return CaptureDeviceConfiguration.GetDefaultAudioCaptureDevice();  
  157.             }  
  158.         }  
  159.         public static ReadOnlyCollection<AudioCaptureDevice> AvailableAudioDevice  
  160.         {  
  161.             get  
  162.             {  
  163.                 return CaptureDeviceConfiguration.GetAvailableAudioCaptureDevices();  
  164.             }  
  165.         }  
  166.   
  167.         public AudioCaptureDevice AudioDevice  
  168.         {  
  169.             get;  
  170.             set;  
  171.         }  
  172.   
  173.         private Object lockObj = new object();  
  174.         internal VideoInputFormatInfo videoInputFormatInfo;  
  175.         internal AudioInputFormatInfo audioInputFormatInfo;  
  176.         internal VideoOutputFormatInfo videoOutputFormatInfo;  
  177.         internal AudioOutputFormatInfo audioOutputFormatInfo;  
  178.         internal OutputContainerInfo outputContainerInfo;  
  179.         /// <summary>  
  180.         /// 视频录制  
  181.         /// </summary>  
  182.         public void StartRecord()  
  183.         {  
  184.             lock (lockObj)  
  185.             {  
  186.                 if (this.SessionState == EncodeSessionState.Stop)  
  187.                 {  
  188.                     _videosink = new VideosinkExtensions(this);  
  189.                     _audioSink = new AudioSinkExtensions(this);  
  190.                     //_audioSink.VolumnChange += new AudioSinkExtensions.VolumnChangeHanlder(_audioSink_VolumnChange);  
  191.                     if (_encodeSession == null)  
  192.                     {  
  193.                         _encodeSession = new EncodeSession();  
  194.                     }  
  195.                     PrepareFormatInfo(_cSource.VideoCaptureDevice.DesiredFormat, _cSource.AudioCaptureDevice.DesiredFormat);  
  196.                     _encodeSession.Prepare(videoInputFormatInfo, audioInputFormatInfo, videoOutputFormatInfo, audioOutputFormatInfo, outputContainerInfo);  
  197.                     _encodeSession.Start(false, 200);  
  198.                     this.SessionState = EncodeSessionState.Start;  
  199.                 }  
  200.             }  
  201.         }  
  202.         /// <summary>  
  203.         /// 音量大小指示  
  204.         /// </summary>  
  205.         /// <param name="sender"></param>  
  206.         /// <param name="e"></param>  
  207.         //void _audioSink_VolumnChange(object sender, VolumnChangeArgs e)  
  208.         //{  
  209.         //    this.OwnPage.dispatcher.BeginInvoke(new Action(() =>  
  210.         //    {  
  211.         //        (  
  212.         //            this.OwnPage.Tag as ProgressBar).Value = e.Volumn;  
  213.         //    }));  
  214.         //}  
  215.   
  216.         /// <summary>  
  217.         /// 暂停录制  
  218.         /// </summary>  
  219.         public void PauseRecord()  
  220.         {  
  221.             lock (lockObj)  
  222.             {  
  223.                 this.SessionState = EncodeSessionState.Pause;  
  224.                 _encodeSession.Pause();  
  225.             }  
  226.         }  
  227.         /// <summary>  
  228.         /// 停止录制  
  229.         /// </summary>  
  230.         public void StopRecord()  
  231.         {  
  232.             lock (lockObj)  
  233.             {  
  234.                 this.SessionState = EncodeSessionState.Stop;  
  235.                 _encodeSession.Shutdown();  
  236.                 _videosink = null;  
  237.                 _audioSink = null;  
  238.             }  
  239.         }  
  240.   
  241.         /// <summary>  
  242.         /// 准备编码信息  
  243.         /// </summary>  
  244.         /// <param name="videoFormat"></param>  
  245.         /// <param name="audioFormat"></param>  
  246.         private void PrepareFormatInfo(VideoFormat videoFormat, AudioFormat audioFormat)  
  247.         {  
  248.             uint FrameRateratioNumerator = 0;  
  249.             uint FrameRaterationDenominator = 0;  
  250.             FormatConstants.FrameRatetoRatio((float)Math.Round(videoFormat.FramesPerSecond, 2), ref FrameRateratioNumerator, ref FrameRaterationDenominator);  
  251.   
  252.             videoInputFormatInfo.FrameRateratioNumerator = FrameRateratioNumerator;  
  253.             videoInputFormatInfo.FrameRateratioDenominator = FrameRaterationDenominator;  
  254.             videoInputFormatInfo.FrameWidthInPixels = _videoWidth;  
  255.             videoInputFormatInfo.FrameHeightInPixels = _videoHeight ;  
  256.             videoInputFormatInfo.Stride = (int)_videoWidth*-4;  
  257.   
  258.             videoOutputFormatInfo.FrameRateratioNumerator = FrameRateratioNumerator;  
  259.             videoOutputFormatInfo.FrameRateratioDenominator = FrameRaterationDenominator;  
  260.             videoOutputFormatInfo.FrameWidthInPixels = videoOutputFormatInfo.FrameWidthInPixels == 0 ? (uint)videoFormat.PixelWidth : videoOutputFormatInfo.FrameWidthInPixels;  
  261.             videoOutputFormatInfo.FrameHeightInPixels = videoOutputFormatInfo.FrameHeightInPixels == 0 ? (uint)videoFormat.PixelHeight : videoOutputFormatInfo.FrameHeightInPixels;  
  262.   
  263.             audioInputFormatInfo.BitsPerSample = (uint)audioFormat.BitsPerSample;  
  264.             audioInputFormatInfo.SamplesPerSecond = (uint)audioFormat.SamplesPerSecond;  
  265.             audioInputFormatInfo.ChannelCount = (uint)audioFormat.Channels;  
  266.             if (outputContainerInfo.FilePath == null || outputContainerInfo.FilePath == string.Empty)  
  267.             {  
  268.                 _saveFullPath=System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyVideos), "cCameraRecordVideo.tmp");  
  269.             }  
  270.             outputContainerInfo.FilePath = _saveFullPath;  
  271.             //outputContainerInfo.FilePath = _saveFullPath;  
  272.             if (audioOutputFormatInfo.AverageBitrate == 0)  
  273.                 audioOutputFormatInfo.AverageBitrate = 24000;  
  274.             if (videoOutputFormatInfo.AverageBitrate == 0)  
  275.                 videoOutputFormatInfo.AverageBitrate = 2000000;  
  276.         }  
  277.   
  278.         /// <summary>  
  279.         /// 开始捕获  
  280.         /// </summary>  
  281.         public void StartCaptrue()  
  282.         {  
  283.             if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())  
  284.             {  
  285.                 _cSource.Start();  
  286.             }  
  287.         }  
  288.   
  289.         /// <summary>  
  290.         /// 停止捕获  
  291.         /// </summary>  
  292.         public void StopCapture()  
  293.         {  
  294.             _videosink = null;  
  295.             _audioSink = null;  
  296.             _cSource.Stop();  
  297.         }  
  298.   
  299.         /// <summary>  
  300.         /// 获得视频  
  301.         /// </summary>  
  302.         /// <returns></returns>  
  303.         public VideoBrush GetVideoBrush()  
  304.         {  
  305.             VideoBrush vBrush = new VideoBrush();  
  306.             vBrush.SetSource(_cSource);  
  307.             return vBrush;  
  308.         }  
  309.   
  310.         /// <summary>  
  311.         /// 获得视频  
  312.         /// </summary>  
  313.         /// <returns></returns>  
  314.         public Rectangle GetVideoRectangle()  
  315.         {  
  316.             Rectangle rctg = new Rectangle();  
  317.             rctg.Width = this._videoWidth;  
  318.             rctg.Height = this._videoHeight;  
  319.             rctg.Fill = GetVideoBrush();  
  320.             return rctg;  
  321.         }  
  322.   
  323.         /// <summary>  
  324.         /// 保存视频  
  325.         /// </summary>  
  326.         public void SaveRecord()  
  327.         {  
  328.             if (_saveFullPath == string.Empty)  
  329.             {  
  330.                 MessageBox.Show("尚未录制视频,无法进行保存!""系统提示", MessageBoxButton.OK);  
  331.                 return;  
  332.             }  
  333.             SaveFileDialog sfd = new SaveFileDialog  
  334.             {  
  335.                 Filter = "MP4 Files (*.mp4)|*.mp4",  
  336.                 DefaultExt = ".mp4",  
  337.                 FilterIndex = 1  
  338.             };  
  339.   
  340.             if ((bool)sfd.ShowDialog())  
  341.             {  
  342.                 using (Stream stm=sfd.OpenFile())  
  343.                 {  
  344.                     FileStream fs = new FileStream(_saveFullPath, FileMode.Open, FileAccess.Read);  
  345.                     try  
  346.                     {  
  347.                         byte[] buffur = new byte[fs.Length];  
  348.                         fs.Read(buffur, 0, (int)fs.Length);  
  349.                         stm.Write(buffur, (int)buffur.Length);  
  350.                         fs.Close();  
  351.                         File.Delete(_saveFullPath);  
  352.                     }  
  353.                     catch (IOException ioe)  
  354.                     {  
  355.                         MessageBox.Show("文件保存失败!错误信息如下:"+Environment.NewLine+ioe.Message,"系统提示",MessageBoxButton.OK);  
  356.                     }  
  357.                     stm.Close();  
  358.                 }  
  359.             }  
  360.         }  
  361.     }  
  362. }  

当然上面说过必须有两个Sink:

  1. using System;  
  2. using System.Windows.Media;  
  3. using System.Windows.Controls;  
  4. using Microsoft.Silverlight.Windows.LocalEncode;  
  5.   
  6. namespace Cmj.MyWeb.MySilverlight.SilverlightMeida  
  7. {  
  8.     public class VideosinkExtensions:Videosink  
  9.     {  
  10.         //private UserControl _page;  
  11.         //private EncodeSession _session;  
  12.         private LocalCamera _localCamera;  
  13.         public VideosinkExtensions(LocalCamera localCamera)  
  14.         {  
  15.             //this._page = page;  
  16.             this._localCamera = localCamera;  
  17.             //this._session = session;  
  18.             this.CaptureSource = _localCamera.source;  
  19.         }  
  20.   
  21.         protected override void OnCaptureStarted()  
  22.         {  
  23.               
  24.         }  
  25.   
  26.         protected override void OnCaptureStopped()  
  27.         {  
  28.   
  29.         }  
  30.   
  31.         protected override void OnFormatChange(VideoFormat videoFormat)  
  32.         {  
  33.   
  34.         }  
  35.   
  36.         protected override void OnSample(long sampleTimeInHundrednanoseconds, long frameDurationInHundrednanoseconds, byte[] sampleData)  
  37.         {  
  38.             if (_localCamera.SessionState == EncodeSessionState.Start)  
  39.             {  
  40.                 _localCamera.OwnPage.dispatcher.BeginInvoke(new Action<longlongbyte[]>((ts, dur, data) =>  
  41.                 {  
  42.                     _localCamera.Session.WriteVideoSample(data, data.Length, ts, dur);  
  43.                 }), sampleTimeInHundrednanoseconds, frameDurationInHundrednanoseconds, sampleData);  
  44.             }  
  45.         }  
  46.     }  
  47. }  
  1. using System;  
  2. using System.Windows.Media;  
  3. using System.Windows.Controls;  
  4. using Microsoft.Silverlight.Windows.LocalEncode;  
  5.   
  6.   
  7. namespace Cmj.MyWeb.MySilverlight.SilverlightMeida  
  8. {  
  9.     public class AudioSinkExtensions:AudioSink  
  10.     {  
  11.         private LocalCamera _localCamera;  
  12.         public AudioSinkExtensions(LocalCamera localCamera)  
  13.         {  
  14.             this._localCamera = localCamera;  
  15.             this.CaptureSource = _localCamera.source;  
  16.   
  17.         }  
  18.         protected override void OnCaptureStarted()  
  19.         {  
  20.               
  21.         }  
  22.   
  23.         protected override void OnCaptureStopped()  
  24.         {  
  25.   
  26.         }  
  27.   
  28.         protected override void OnFormatChange(AudioFormat audioFormat)  
  29.         {  
  30.   
  31.         }  
  32.   
  33.         protected override void OnSamples(long sampleTimeInHundrednanoseconds, long sampleDurationInHundrednanoseconds, byte[] sampleData)  
  34.         {  
  35.             if (_localCamera.SessionState == EncodeSessionState.Start)  
  36.             {  
  37.                 _localCamera.OwnPage.dispatcher.BeginInvoke(new Action<long, data) =>  
  38.                 {  
  39.                     _localCamera.Session.WriteAudioSample(data, dur);  
  40.                 }), sampleDurationInHundrednanoseconds, sampleData);  
  41.   
  42.                 //计算音量变化  
  43.                 //for (int index = 0; index < sampleData.Length; index += 1)  
  44.                 //{  
  45.                 //    short sample = (short)((sampleData[index] << 8) | sampleData[index]);  
  46.                 //    float sample32 = sample / 32768f;  
  47.                 //    float maxValue = 0;  
  48.                 //    float minValue = 0;  
  49.                 //    maxValue = Math.Max(maxValue, sample32);  
  50.                 //    minValue = Math.Min(minValue, sample32);  
  51.                 //    float lastPeak = Math.Max(maxValue, Math.Abs(minValue));  
  52.                 //    float micLevel = (100 - (lastPeak * 100)) * 10;  
  53.                 //    OnVolumnChange(this, new VolumnChangeArgs() { Volumn=micLevel});  
  54.                 //}  
  55.             }  
  56.         }  
  57.   
  58.   
  59.         /// <summary>  
  60.         /// 定义一个事件,反馈音量变化  
  61.         /// </summary>  
  62.         /// <param name="sender"></param>  
  63.         /// <param name="e"></param>  
  64.         //public delegate void VolumnChangeHanlder(object sender, VolumnChangeArgs e);  
  65.         //public event VolumnChangeHanlder VolumnChange;  
  66.         //private void OnVolumnChange(object sender, VolumnChangeArgs e)  
  67.         //{  
  68.         //    if (VolumnChange != null)  
  69.         //    {  
  70.         //        VolumnChange(sender, e);  
  71.         //    }  
  72.         //}  
  73.     }  
  74.   
  75.     //public class VolumnChangeArgs : EventArgs  
  76.     //{  
  77.     //    public float Volumn  
  78.     //    {  
  79.     //        get;  
  80.     //        internal set;  
  81.     //    }  
  82.     //}  
  83. }  

有了这三个类,下面准备一个界面,使用LocalCamera进行视频录制操作。

recordUI

需要注意的是保存操作,事实上在EncodeSession中视频的保存路径是在视频录制之前就必须指定的(当然这一点并不难理解,因为长时间的视频录制是会形成很大的文件的,保存之前缓存到内存中也不是很现实),在LocalCamera中对保存方法的封装事实上是文件的读取和删除操作。另外在这个例子中用到了前面文章自定义的OOB控件,不明白的朋友可以查看前面的文章内容。下面是调用代码

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Net;  
  5. using System.Windows;  
  6. using System.Windows.Controls;  
  7. using System.Windows.Documents;  
  8. using System.Windows.Input;  
  9. using System.Windows.Media;  
  10. using System.Windows.Media.Animation;  
  11. using System.Windows.Shapes;  
  12. using System.Windows.Threading;  
  13. using Cmj.MyWeb.MySilverlight.SiverlightOOB;  
  14. using Cmj.MyWeb.MySilverlight.SilverlightMeida;  
  15.   
  16. namespace SilverlightVideoRecord  
  17. {  
  18.     public partial class MainPage : UserControl  
  19.     {  
  20.         public MainPage()  
  21.         {  
  22.             InitializeComponent();  
  23.         }  
  24.   
  25.         OOBInstall install = new OOBInstall();  
  26.         LocalCamera localCamera = null;  
  27.         dispatcherTimer timer = null;  
  28.         private DateTime startTime = DateTime.Now;  
  29.         private void UserControl_Loaded(object sender, RoutedEventArgs e)  
  30.         {  
  31.             timer = new dispatcherTimer();  
  32.             timer.Interval = TimeSpan.FromSeconds(1);  
  33.             timer.Tick += new EventHandler(timer_Tick);  
  34.             if (install.IsRunOutOfbrowser)  
  35.             {  
  36.                 this.btnInstall.Visibility = Visibility.Collapsed;  
  37.                 localCamera = new LocalCamera(this,LocalCamera.AvailableVideoDevice[1].SupportedFormats[0],LocalCamera.DefaultAudioDevice.SupportedFormats[1]);  
  38.                 this.bdVideo.Child = localCamera.GetVideoRectangle();  
  39.                 //this.Tag = this.pbVolumn;  
  40.             }  
  41.             else  
  42.             {  
  43.                 this.btnInstall.Visibility = Visibility.Visible;  
  44.                 this.btnStart.IsEnabled = false;  
  45.                 this.btnPause.IsEnabled = false;  
  46.                 this.btnStop.IsEnabled = false;  
  47.                 this.btnSave.IsEnabled = false;  
  48.                 //this.tbTitleBar.IsEnabled = false;  
  49.                 //this.rbResizeButton.IsEnabled = false;  
  50.             }  
  51.         }  
  52.   
  53.         void timer_Tick(object sender, EventArgs e)  
  54.         {  
  55.             TimeSpan tsstart = new TimeSpan(startTime.Ticks);  
  56.             TimeSpan tsEnd = new TimeSpan(DateTime.Now.Ticks);  
  57.             TimeSpan tsTract = tsEnd.Subtract(tsstart);  
  58.             DateTime timeInterval = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, tsTract.Hours, tsTract.Minutes, tsTract.Seconds);  
  59.             //this.txtblkTimer.Text = string.Format("{0}:{1}:{2}",tsTract.Minutes,tsTract.Seconds);  
  60.             this.txtblkTimer.Text = timeInterval.ToLongTimeString();  
  61.         }  
  62.   
  63.         private void btnStart_Click(object sender, RoutedEventArgs e)  
  64.         {  
  65.             localCamera.StartCaptrue();//启动视频捕获  
  66.         }  
  67.   
  68.         private void btnRecord_Click(object sender, RoutedEventArgs e)  
  69.         {  
  70.             localCamera.StartRecord();//开始录制  
  71.             this.txtblkTimer.Text = "0:00:00";  
  72.             this.startTime = DateTime.Now;  
  73.             timer.Start();  
  74.         }  
  75.   
  76.         private void btnPause_Click(object sender, RoutedEventArgs e)  
  77.         {  
  78.             localCamera.PauseRecord();//暂停录制  
  79.             timer.Stop();  
  80.         }  
  81.   
  82.         private void btnStop_Click(object sender, RoutedEventArgs e)  
  83.         {  
  84.             localCamera.StopRecord();//停止录制  
  85.             localCamera.StopCapture();//停止视频捕获  
  86.             timer.Stop();  
  87.         }  
  88.   
  89.         private void btnSave_Click(object sender, RoutedEventArgs e)  
  90.         {  
  91.             localCamera.SaveRecord();//保存视频  
  92.         }  
  93.   
  94.         private void btnInstall_Click(object sender, RoutedEventArgs e)  
  95.         {  
  96.             install.Install();  
  97.         }  
  98.     }  
  99. }  

OK,下面是视频录制的截图:

正在录制

 

recordStop

停止录制后保存

saveRecord

播放录制的视频

recordVideoPlay

三、注意:

1.video sink和audio sink都是运行在不同于UI的各自的线程中,你可以使用UI的dispathcher或者SynchronizationContext进行不同线程之间的调用

2.在video sink和audio sink的OnSample方法中必须进行状态判断,因为sink实例创建之后就会执行OnSample方法,但此时EncodeSession还没有启动因此如果不进行状态判读就会抛出com异常。

3.视频的宽度和高度不能够随意指定,这个在nesL的帮助文档中也是特意说明的,如果任意指定同样会抛出异常。

4.最后再次提醒大家,上面的视频录制是基于nesL的因此必须将应用运行到浏览器外(OOB)。

代码下载

download

知识共享许可协议

作品采用知识共享署名 2.5 中国大陆许可协议进行许可,欢迎转载,演绎或用于商业目的。但转载请注明来自崔江涛(KenshinCui),并包含相关链接

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐