稳扎稳打Silverlight(49) - 4.0媒体之摄像头和麦克风
稳扎稳打Silverlight(49) - 4.0媒体之摄像头和麦克风
作者:webabcd
介绍
Silverlight 4.0 媒体方面的增强:
- 新增对摄像头的支持
- 新增对麦克风的支持
在线DEMO
http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html
示例
1、演示如何捕获摄像头
MemoryStreamVideoSink.cs
代码
/*
* VideoSink - 用于捕获视频信息。抽象类,其有一个 CaptureSource 类型的属性
*/
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
namespace Silverlight40.WebcamMic
{
public class MemoryStreamVideoSink : VideoSink
{
public VideoFormat VideoFormat { get; private set; }
public MemoryStream MemoryStream { get; private set; }
// 当视频设备开始捕获视频数据时所调用的方法
protected override void OnCaptureStarted()
{
MemoryStream = new MemoryStream();
}
// 当视频设备停止捕获视频数据时所调用的方法
protected override void OnCaptureStopped()
{
}
/// <summary>
/// 当视频设备报告视频格式更改时所调用的方法
/// 当视频设备开始捕获视频数据时会调用一次 OnFormatChange,此时便可以确定当前的视频格式
/// </summary>
/// <param name="videoFormat">新的视频格式</param>
protected override void OnFormatChange(VideoFormat videoFormat)
{
VideoFormat = videoFormat;
}
/// <summary>
/// 当视频设备捕获了一个完整的视频采样时所调用的方法
/// </summary>
/// <param name="sampleTime">当前采样被捕获时的时间。单位:100纳秒</param>
/// <param name="frameDuration">当前采样的时长。单位:100纳秒</param>
/// <param name="sampleData">当前采样的视频数据的字节流</param>
protected override void OnSample(long sampleTime, long frameDuration, byte[] sampleData)
{
MemoryStream.Write(sampleData, 0, sampleData.Length);
}
}
}
* VideoSink - 用于捕获视频信息。抽象类,其有一个 CaptureSource 类型的属性
*/
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
namespace Silverlight40.WebcamMic
{
public class MemoryStreamVideoSink : VideoSink
{
public VideoFormat VideoFormat { get; private set; }
public MemoryStream MemoryStream { get; private set; }
// 当视频设备开始捕获视频数据时所调用的方法
protected override void OnCaptureStarted()
{
MemoryStream = new MemoryStream();
}
// 当视频设备停止捕获视频数据时所调用的方法
protected override void OnCaptureStopped()
{
}
/// <summary>
/// 当视频设备报告视频格式更改时所调用的方法
/// 当视频设备开始捕获视频数据时会调用一次 OnFormatChange,此时便可以确定当前的视频格式
/// </summary>
/// <param name="videoFormat">新的视频格式</param>
protected override void OnFormatChange(VideoFormat videoFormat)
{
VideoFormat = videoFormat;
}
/// <summary>
/// 当视频设备捕获了一个完整的视频采样时所调用的方法
/// </summary>
/// <param name="sampleTime">当前采样被捕获时的时间。单位:100纳秒</param>
/// <param name="frameDuration">当前采样的时长。单位:100纳秒</param>
/// <param name="sampleData">当前采样的视频数据的字节流</param>
protected override void OnSample(long sampleTime, long frameDuration, byte[] sampleData)
{
MemoryStream.Write(sampleData, 0, sampleData.Length);
}
}
}
Webcam.xaml
代码
<navigation:Page x:Class="Silverlight40.WebcamMic.Webcam"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
Title="Webcam Page">
<Grid x:Name="LayoutRoot">
<StackPanel HorizontalAlignment="Left">
<TextBlock Text="可用的视频捕获设备列表" />
<ListBox Name="videoSources">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--显示 CaptureSource 中的视频-->
<Border Width="320" Height="240" CornerRadius="10" BorderThickness="1" BorderBrush="Blue">
<Rectangle Name="webcamCapture" Fill="Black"/>
</Border>
<Button Name="btnStartCapture" Content="开始捕获" Click="btnStartCapture_Click" />
<Button Name="btnStopCapture" Content="停止捕获" Click="btnStopCapture_Click" />
<Button Name="btnTakeSnapshot" Content="截图" Click="btnTakeSnapshot_Click" />
<!--显示截图结果-->
<ScrollViewer Width="320" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto">
<ItemsControl Name="snapshots">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Margin="3" Stretch="Fill" Height="50" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</Grid>
</navigation:Page>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
Title="Webcam Page">
<Grid x:Name="LayoutRoot">
<StackPanel HorizontalAlignment="Left">
<TextBlock Text="可用的视频捕获设备列表" />
<ListBox Name="videoSources">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--显示 CaptureSource 中的视频-->
<Border Width="320" Height="240" CornerRadius="10" BorderThickness="1" BorderBrush="Blue">
<Rectangle Name="webcamCapture" Fill="Black"/>
</Border>
<Button Name="btnStartCapture" Content="开始捕获" Click="btnStartCapture_Click" />
<Button Name="btnStopCapture" Content="停止捕获" Click="btnStopCapture_Click" />
<Button Name="btnTakeSnapshot" Content="截图" Click="btnTakeSnapshot_Click" />
<!--显示截图结果-->
<ScrollViewer Width="320" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto">
<ItemsControl Name="snapshots">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Margin="3" Stretch="Fill" Height="50" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</Grid>
</navigation:Page>
Webcam.xaml.cs
代码
/*
* 演示 Silverlight 4.0 对视频捕获设备的支持
* CaptureDeviceConfiguration - 视频捕获设备及音频捕获设备的相关信息
* GetAvailableVideoCaptureDevices() - 返回可用的视频捕获设备的集合。VideoCaptureDevice 类型的集合
* GetDefaultVideoCaptureDevice() - 返回默认的视频捕获设备。VideoCaptureDevice 类型
* RequestDeviceAccess() - 请求访问所有可能的视频捕获设备和音频捕获设备。弹出确认对话框后(被信任的应用程序不会弹出此对话框),用户允许则返回 true
* AllowedDeviceAccess - 用户以前是否允许了可以访问视频捕获设备和音频捕获设备(当用户以前允许过,并且允许的时候选择了“记住我的答案”,则返回 true)
*
* CaptureSource - 捕获源,用于提供捕获视频和音频的一些相关方法
* Start() - 开始捕获
* Stop() - 停止捕获
* VideoCaptureDevice - 指定用于捕获视频的设备, VideoCaptureDevice 类型
* State - 捕获状态 [System.Windows.Media.CaptureState 枚举(Stopped, Started, Failed)]
* CaptureImageAsync() - 启动一个异步图像捕获请求
* CaptureImageCompleted - 当异步图像捕获请求完成时所触发的事件
* CaptureFailed - 捕获失败时所触发的事件
*
* VideoCaptureDevice - 视频捕获设备的相关信息
* FriendlyName - 视频捕获设备的名称
* IsDefaultDevice - 是否是默认的视频捕获设备
* SupportedFormats - 此视频捕获设备所支持的视频格式的集合。VideoFormat 类型的集合
* DesiredFormat - 需要视频捕获设备使用的视频格式。VideoFormat 类型
*
* VideoFormat - 捕获视频的视频格式信息
* PixelWidth - 视频区域的宽度,以像素为单位
* PixelHeight - 视频区域的高度,以像素为单位
* PixelFormat - 视频编码格式 [System.Windows.Media.PixelFormatType 枚举],目前仅支持 PixelFormatType.Format32bppArgb
* FramesPerSecond - 视频的每秒帧数
* Stride - 图像的行的宽度,以字节为单位,如果是负数则表示图像倒置
*
* VideoBrush.SetSource(CaptureSource) - 指定一个视频捕获源做为 VideoBrush 的源
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
using System.IO;
namespace Silverlight40.WebcamMic
{
public partial class Webcam : Page
{
private CaptureSource _captureSource;
private MemoryStreamVideoSink _videoSink;
private ObservableCollection<WriteableBitmap> _images = new ObservableCollection<WriteableBitmap>();
public Webcam()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// 可用的视频捕获设备列表
videoSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices();
_captureSource = new CaptureSource();
_captureSource.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
// 截图完成
_captureSource.CaptureImageCompleted += ((s, args) => { _images.Add(args.Result); });
// 视频截图列表
snapshots.ItemsSource = _images;
// VideoSink 用于处理捕获视频信息的相关逻辑
_videoSink = new MemoryStreamVideoSink();
_videoSink.CaptureSource = _captureSource;
}
private void btnStartCapture_Click(object sender, RoutedEventArgs e)
{
// 将视频捕获框填充到指定的 Rectangle 中
VideoBrush videoBrush = new VideoBrush();
videoBrush.SetSource(_captureSource);
webcamCapture.Fill = videoBrush;
// 如果允许启用摄像头,则开始捕获
if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
_captureSource.Start();
}
private void btnStopCapture_Click(object sender, RoutedEventArgs e)
{
_captureSource.Stop();
}
private void btnTakeSnapshot_Click(object sender, RoutedEventArgs e)
{
_captureSource.CaptureImageAsync();
}
}
}
* 演示 Silverlight 4.0 对视频捕获设备的支持
* CaptureDeviceConfiguration - 视频捕获设备及音频捕获设备的相关信息
* GetAvailableVideoCaptureDevices() - 返回可用的视频捕获设备的集合。VideoCaptureDevice 类型的集合
* GetDefaultVideoCaptureDevice() - 返回默认的视频捕获设备。VideoCaptureDevice 类型
* RequestDeviceAccess() - 请求访问所有可能的视频捕获设备和音频捕获设备。弹出确认对话框后(被信任的应用程序不会弹出此对话框),用户允许则返回 true
* AllowedDeviceAccess - 用户以前是否允许了可以访问视频捕获设备和音频捕获设备(当用户以前允许过,并且允许的时候选择了“记住我的答案”,则返回 true)
*
* CaptureSource - 捕获源,用于提供捕获视频和音频的一些相关方法
* Start() - 开始捕获
* Stop() - 停止捕获
* VideoCaptureDevice - 指定用于捕获视频的设备, VideoCaptureDevice 类型
* State - 捕获状态 [System.Windows.Media.CaptureState 枚举(Stopped, Started, Failed)]
* CaptureImageAsync() - 启动一个异步图像捕获请求
* CaptureImageCompleted - 当异步图像捕获请求完成时所触发的事件
* CaptureFailed - 捕获失败时所触发的事件
*
* VideoCaptureDevice - 视频捕获设备的相关信息
* FriendlyName - 视频捕获设备的名称
* IsDefaultDevice - 是否是默认的视频捕获设备
* SupportedFormats - 此视频捕获设备所支持的视频格式的集合。VideoFormat 类型的集合
* DesiredFormat - 需要视频捕获设备使用的视频格式。VideoFormat 类型
*
* VideoFormat - 捕获视频的视频格式信息
* PixelWidth - 视频区域的宽度,以像素为单位
* PixelHeight - 视频区域的高度,以像素为单位
* PixelFormat - 视频编码格式 [System.Windows.Media.PixelFormatType 枚举],目前仅支持 PixelFormatType.Format32bppArgb
* FramesPerSecond - 视频的每秒帧数
* Stride - 图像的行的宽度,以字节为单位,如果是负数则表示图像倒置
*
* VideoBrush.SetSource(CaptureSource) - 指定一个视频捕获源做为 VideoBrush 的源
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
using System.IO;
namespace Silverlight40.WebcamMic
{
public partial class Webcam : Page
{
private CaptureSource _captureSource;
private MemoryStreamVideoSink _videoSink;
private ObservableCollection<WriteableBitmap> _images = new ObservableCollection<WriteableBitmap>();
public Webcam()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// 可用的视频捕获设备列表
videoSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices();
_captureSource = new CaptureSource();
_captureSource.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
// 截图完成
_captureSource.CaptureImageCompleted += ((s, args) => { _images.Add(args.Result); });
// 视频截图列表
snapshots.ItemsSource = _images;
// VideoSink 用于处理捕获视频信息的相关逻辑
_videoSink = new MemoryStreamVideoSink();
_videoSink.CaptureSource = _captureSource;
}
private void btnStartCapture_Click(object sender, RoutedEventArgs e)
{
// 将视频捕获框填充到指定的 Rectangle 中
VideoBrush videoBrush = new VideoBrush();
videoBrush.SetSource(_captureSource);
webcamCapture.Fill = videoBrush;
// 如果允许启用摄像头,则开始捕获
if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
_captureSource.Start();
}
private void btnStopCapture_Click(object sender, RoutedEventArgs e)
{
_captureSource.Stop();
}
private void btnTakeSnapshot_Click(object sender, RoutedEventArgs e)
{
_captureSource.CaptureImageAsync();
}
}
}
2、演示如何捕获麦克风
MemoryStreamAudioSink.cs
代码
/*
* AudioSink - 用于捕获音频信息。抽象类,其有一个 CaptureSource 类型的属性
*/
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
namespace Silverlight40.WebcamMic
{
public class MemoryStreamAudioSink : AudioSink
{
public AudioFormat AudioFormat { get; private set; }
public MemoryStream MemoryStream { get; private set; }
// 当音频设备开始捕获音频数据时所调用的方法
protected override void OnCaptureStarted()
{
MemoryStream = new MemoryStream();
}
// 当音频设备停止捕获音频数据时所调用的方法
protected override void OnCaptureStopped()
{
}
/// <summary>
/// 当音频设备报告音频格式更改时所调用的方法
/// 当音频设备开始捕获音频数据时会调用一次 OnFormatChange,此时便可以确定当前的音频格式
/// </summary>
/// <param name="audioFormat">新的音频格式</param>
protected override void OnFormatChange(AudioFormat audioFormat)
{
AudioFormat = audioFormat;
}
/// <summary>
/// 当音频设备捕获了一个完整的音频采样时所调用的方法
/// </summary>
/// <param name="sampleTime">当前采样被捕获时的时间。单位:100纳秒</param>
/// <param name="sampleDuration">当前采样的时长。单位:100纳秒</param>
/// <param name="sampleData">当前采样的音频数据的字节流</param>
protected override void OnSamples(long sampleTime, long sampleDuration, byte[] sampleData)
{
MemoryStream.Write(sampleData, 0, sampleData.Length);
}
}
}
* AudioSink - 用于捕获音频信息。抽象类,其有一个 CaptureSource 类型的属性
*/
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
namespace Silverlight40.WebcamMic
{
public class MemoryStreamAudioSink : AudioSink
{
public AudioFormat AudioFormat { get; private set; }
public MemoryStream MemoryStream { get; private set; }
// 当音频设备开始捕获音频数据时所调用的方法
protected override void OnCaptureStarted()
{
MemoryStream = new MemoryStream();
}
// 当音频设备停止捕获音频数据时所调用的方法
protected override void OnCaptureStopped()
{
}
/// <summary>
/// 当音频设备报告音频格式更改时所调用的方法
/// 当音频设备开始捕获音频数据时会调用一次 OnFormatChange,此时便可以确定当前的音频格式
/// </summary>
/// <param name="audioFormat">新的音频格式</param>
protected override void OnFormatChange(AudioFormat audioFormat)
{
AudioFormat = audioFormat;
}
/// <summary>
/// 当音频设备捕获了一个完整的音频采样时所调用的方法
/// </summary>
/// <param name="sampleTime">当前采样被捕获时的时间。单位:100纳秒</param>
/// <param name="sampleDuration">当前采样的时长。单位:100纳秒</param>
/// <param name="sampleData">当前采样的音频数据的字节流</param>
protected override void OnSamples(long sampleTime, long sampleDuration, byte[] sampleData)
{
MemoryStream.Write(sampleData, 0, sampleData.Length);
}
}
}
WavFileHelper.cs
代码
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
namespace Silverlight40.WebcamMic
{
public static class WavFileHelper
{
// 获取 PCM 格式的音频头的字节数组
public static byte[] GetWavFileHeader(long audioByteLength, AudioFormat audioFormat)
{
MemoryStream stream = new MemoryStream(44);
// “RIFF”
stream.Write(new byte[] { 0x52, 0x49, 0x46, 0x46 }, 0, 4);
// 文件长度 = 音频数据长度 + 44个字节的header长度 - 8个字节(上面的4个字节和这里的4个字节)
stream.Write(BitConverter.GetBytes((UInt32)(audioByteLength + 44 - 8)), 0, 4);
// “WAVE”
stream.Write(new byte[] { 0x57, 0x41, 0x56, 0x45 }, 0, 4);
// “fmt ”
stream.Write(new byte[] { 0x66, 0x6D, 0x74, 0x20 }, 0, 4);
// 对于 PCM 来说,这里的值为 16
stream.Write(BitConverter.GetBytes((UInt32)16), 0, 4);
// “1”代表未压缩
stream.Write(BitConverter.GetBytes((UInt16)1), 0, 2);
// 通道数:“1”代表单声道;“2”代表双声道
stream.Write(BitConverter.GetBytes((UInt16)audioFormat.Channels), 0, 2);
// 采样率(采样频率),即每秒样本数
stream.Write(BitConverter.GetBytes((UInt32)audioFormat.SamplesPerSecond), 0, 4);
// 比特率,即每秒字节数。其值为通道数×每秒数据位数×每样本的数据位数/8(SampleRate * ChannelCount * BitsPerSample / 8)
stream.Write(BitConverter.GetBytes((UInt32)((audioFormat.SamplesPerSecond * audioFormat.Channels * audioFormat.BitsPerSample) / 8)), 0, 4);
// 通道数×每样本的数据位数/8(ChannelCount * BitsPerSample / 8)
stream.Write(BitConverter.GetBytes((UInt16)((audioFormat.Channels * audioFormat.BitsPerSample) / 8)), 0, 2);
// 采样位数(采样分辨率),即每样本的数据位数
stream.Write(BitConverter.GetBytes((UInt16)audioFormat.BitsPerSample), 0, 2);
// “data”
stream.Write(new byte[] { 0x64, 0x61, 0x74, 0x61 }, 0, 4);
// 语音数据的长度
stream.Write(BitConverter.GetBytes((UInt32)audioByteLength), 0, 4);
return (stream.GetBuffer());
}
}
}
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
namespace Silverlight40.WebcamMic
{
public static class WavFileHelper
{
// 获取 PCM 格式的音频头的字节数组
public static byte[] GetWavFileHeader(long audioByteLength, AudioFormat audioFormat)
{
MemoryStream stream = new MemoryStream(44);
// “RIFF”
stream.Write(new byte[] { 0x52, 0x49, 0x46, 0x46 }, 0, 4);
// 文件长度 = 音频数据长度 + 44个字节的header长度 - 8个字节(上面的4个字节和这里的4个字节)
stream.Write(BitConverter.GetBytes((UInt32)(audioByteLength + 44 - 8)), 0, 4);
// “WAVE”
stream.Write(new byte[] { 0x57, 0x41, 0x56, 0x45 }, 0, 4);
// “fmt ”
stream.Write(new byte[] { 0x66, 0x6D, 0x74, 0x20 }, 0, 4);
// 对于 PCM 来说,这里的值为 16
stream.Write(BitConverter.GetBytes((UInt32)16), 0, 4);
// “1”代表未压缩
stream.Write(BitConverter.GetBytes((UInt16)1), 0, 2);
// 通道数:“1”代表单声道;“2”代表双声道
stream.Write(BitConverter.GetBytes((UInt16)audioFormat.Channels), 0, 2);
// 采样率(采样频率),即每秒样本数
stream.Write(BitConverter.GetBytes((UInt32)audioFormat.SamplesPerSecond), 0, 4);
// 比特率,即每秒字节数。其值为通道数×每秒数据位数×每样本的数据位数/8(SampleRate * ChannelCount * BitsPerSample / 8)
stream.Write(BitConverter.GetBytes((UInt32)((audioFormat.SamplesPerSecond * audioFormat.Channels * audioFormat.BitsPerSample) / 8)), 0, 4);
// 通道数×每样本的数据位数/8(ChannelCount * BitsPerSample / 8)
stream.Write(BitConverter.GetBytes((UInt16)((audioFormat.Channels * audioFormat.BitsPerSample) / 8)), 0, 2);
// 采样位数(采样分辨率),即每样本的数据位数
stream.Write(BitConverter.GetBytes((UInt16)audioFormat.BitsPerSample), 0, 2);
// “data”
stream.Write(new byte[] { 0x64, 0x61, 0x74, 0x61 }, 0, 4);
// 语音数据的长度
stream.Write(BitConverter.GetBytes((UInt32)audioByteLength), 0, 4);
return (stream.GetBuffer());
}
}
}
Mic.xaml
代码
<navigation:Page x:Class="Silverlight40.WebcamMic.Mic"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
Title="Mic Page">
<Grid x:Name="LayoutRoot">
<StackPanel HorizontalAlignment="Left">
<TextBlock Text="可用的音频捕获设备列表" />
<ListBox Name="audioSources">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Name="lblMsg" />
<Button Name="btnStartCapture" Content="开始捕获" Click="btnStartCapture_Click" />
<Button Name="btnStopCapture" Content="停止捕获" Click="btnStopCapture_Click" />
</StackPanel>
</Grid>
</navigation:Page>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
Title="Mic Page">
<Grid x:Name="LayoutRoot">
<StackPanel HorizontalAlignment="Left">
<TextBlock Text="可用的音频捕获设备列表" />
<ListBox Name="audioSources">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBlock Name="lblMsg" />
<Button Name="btnStartCapture" Content="开始捕获" Click="btnStartCapture_Click" />
<Button Name="btnStopCapture" Content="停止捕获" Click="btnStopCapture_Click" />
</StackPanel>
</Grid>
</navigation:Page>
Mic.xaml.cs
代码
/*
* 演示 Silverlight 4.0 对音频捕获设备的支持
* CaptureDeviceConfiguration - 视频捕获设备及音频捕获设备的相关信息
* GetAvailableAudioCaptureDevices() - 返回可用的音频捕获设备的集合。AudioCaptureDevice 类型的集合
* GetDefaultAudioCaptureDevice() - 返回默认的音频捕获设备。AudioCaptureDevice 类型
* RequestDeviceAccess() - 请求访问所有可能的视频捕获设备和音频捕获设备。弹出确认对话框后(被信任的应用程序不会弹出此对话框),用户允许则返回 true
* AllowedDeviceAccess - 用户以前是否允许了可以访问视频捕获设备和音频捕获设备(当用户以前允许过,并且允许的时候选择了“记住我的答案”,则返回 true)
*
* CaptureSource - 捕获源,用于提供捕获视频和音频的一些相关方法
* Start() - 开始捕获
* Stop() - 停止捕获
* AudioCaptureDevice - 指定用于捕获音频的设备, AudioCaptureDevice 类型
* State - 捕获状态 [System.Windows.Media.CaptureState 枚举(Stopped, Started, Failed)]
* CaptureFailed - 捕获失败时所触发的事件
*
* AudioCaptureDevice - 音频捕获设备的相关信息
* FriendlyName - 音频捕获设备的名称
* IsDefaultDevice - 是否是默认的音频捕获设备
* SupportedFormats - 此音频捕获设备所支持的音频格式的集合。AudioFormat 类型的集合
* DesiredFormat - 需要音频捕获设备使用的音频格式。AudioFormat 类型
* AudioFrameSize - 音频的帧大小。单位:毫秒。默认值:1000毫秒。范围:10 - 2000毫秒
*
* AudioFormat - 捕获音频的音频格式信息
* Channels - 声道数
* SamplesPerSecond - 采样率(采样频率)
* BitsPerSample - 采样位数(采样分辨率)
* WaveFormat - 音频编码格式 [System.Windows.Media.WaveFormatType 枚举],目前仅支持 WaveFormatType.Pcm
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using System.IO;
namespace Silverlight40.WebcamMic
{
public partial class Mic : Page
{
private CaptureSource _captureSource;
private MemoryStreamAudioSink _audioSink;
public Mic()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// 可用的音频捕获设备列表
audioSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableAudioCaptureDevices();
_captureSource = new CaptureSource();
_captureSource.AudioCaptureDevice = CaptureDeviceConfiguration.GetDefaultAudioCaptureDevice();
// AudioSink 用于处理捕获音频信息的相关逻辑
_audioSink = new MemoryStreamAudioSink();
_audioSink.CaptureSource = _captureSource;
}
private void btnStartCapture_Click(object sender, RoutedEventArgs e)
{
// 如果允许启用麦克风,则开始捕获
if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
_captureSource.Start();
lblMsg.Text = _captureSource.State.ToString();
}
private void btnStopCapture_Click(object sender, RoutedEventArgs e)
{
_captureSource.Stop();
lblMsg.Text = _captureSource.State.ToString();
if (_audioSink.MemoryStream == null)
return;
// 弹出“另存为”对话框,保存捕获到的全部音频数据
SaveFileDialog dialog = new SaveFileDialog();
dialog.Filter = "音频(*.wav)|*.wav";
bool? result = dialog.ShowDialog();
if (result == true)
{
using (Stream stream = dialog.OpenFile())
{
// 写入音频头
byte[] wavFileHeader = WavFileHelper.GetWavFileHeader(_audioSink.MemoryStream.Length, _audioSink.AudioFormat);
stream.Write(wavFileHeader, 0, wavFileHeader.Length);
byte[] buffer = new byte[4096];
int read = 0;
_audioSink.MemoryStream.Seek(0, SeekOrigin.Begin);
// 写入音频数据
while ((read = _audioSink.MemoryStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, read);
}
}
}
}
}
}
* 演示 Silverlight 4.0 对音频捕获设备的支持
* CaptureDeviceConfiguration - 视频捕获设备及音频捕获设备的相关信息
* GetAvailableAudioCaptureDevices() - 返回可用的音频捕获设备的集合。AudioCaptureDevice 类型的集合
* GetDefaultAudioCaptureDevice() - 返回默认的音频捕获设备。AudioCaptureDevice 类型
* RequestDeviceAccess() - 请求访问所有可能的视频捕获设备和音频捕获设备。弹出确认对话框后(被信任的应用程序不会弹出此对话框),用户允许则返回 true
* AllowedDeviceAccess - 用户以前是否允许了可以访问视频捕获设备和音频捕获设备(当用户以前允许过,并且允许的时候选择了“记住我的答案”,则返回 true)
*
* CaptureSource - 捕获源,用于提供捕获视频和音频的一些相关方法
* Start() - 开始捕获
* Stop() - 停止捕获
* AudioCaptureDevice - 指定用于捕获音频的设备, AudioCaptureDevice 类型
* State - 捕获状态 [System.Windows.Media.CaptureState 枚举(Stopped, Started, Failed)]
* CaptureFailed - 捕获失败时所触发的事件
*
* AudioCaptureDevice - 音频捕获设备的相关信息
* FriendlyName - 音频捕获设备的名称
* IsDefaultDevice - 是否是默认的音频捕获设备
* SupportedFormats - 此音频捕获设备所支持的音频格式的集合。AudioFormat 类型的集合
* DesiredFormat - 需要音频捕获设备使用的音频格式。AudioFormat 类型
* AudioFrameSize - 音频的帧大小。单位:毫秒。默认值:1000毫秒。范围:10 - 2000毫秒
*
* AudioFormat - 捕获音频的音频格式信息
* Channels - 声道数
* SamplesPerSecond - 采样率(采样频率)
* BitsPerSample - 采样位数(采样分辨率)
* WaveFormat - 音频编码格式 [System.Windows.Media.WaveFormatType 枚举],目前仅支持 WaveFormatType.Pcm
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using System.IO;
namespace Silverlight40.WebcamMic
{
public partial class Mic : Page
{
private CaptureSource _captureSource;
private MemoryStreamAudioSink _audioSink;
public Mic()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// 可用的音频捕获设备列表
audioSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableAudioCaptureDevices();
_captureSource = new CaptureSource();
_captureSource.AudioCaptureDevice = CaptureDeviceConfiguration.GetDefaultAudioCaptureDevice();
// AudioSink 用于处理捕获音频信息的相关逻辑
_audioSink = new MemoryStreamAudioSink();
_audioSink.CaptureSource = _captureSource;
}
private void btnStartCapture_Click(object sender, RoutedEventArgs e)
{
// 如果允许启用麦克风,则开始捕获
if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
_captureSource.Start();
lblMsg.Text = _captureSource.State.ToString();
}
private void btnStopCapture_Click(object sender, RoutedEventArgs e)
{
_captureSource.Stop();
lblMsg.Text = _captureSource.State.ToString();
if (_audioSink.MemoryStream == null)
return;
// 弹出“另存为”对话框,保存捕获到的全部音频数据
SaveFileDialog dialog = new SaveFileDialog();
dialog.Filter = "音频(*.wav)|*.wav";
bool? result = dialog.ShowDialog();
if (result == true)
{
using (Stream stream = dialog.OpenFile())
{
// 写入音频头
byte[] wavFileHeader = WavFileHelper.GetWavFileHeader(_audioSink.MemoryStream.Length, _audioSink.AudioFormat);
stream.Write(wavFileHeader, 0, wavFileHeader.Length);
byte[] buffer = new byte[4096];
int read = 0;
_audioSink.MemoryStream.Seek(0, SeekOrigin.Begin);
// 写入音频数据
while ((read = _audioSink.MemoryStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, read);
}
}
}
}
}
}
OK
[源码下载]