wpf 语音通话_WPF+WCF一步一步打造音频聊天室(四):视频会话
前面三篇文章中,我实现了音频聊天室的部分功能,包括:文字聊天,共享白板,语音聊天。这篇文章我将叙述一下视频会话实现的技术要点。
在Silerlight4中已经集成了摄像和采集声音的功能,但是在WPF4中却没有直接可以用的的控件,由此也可以看出,由桌面程序走向web程序的大趋势。如果你想用Silverlight实现类似的音频聊天室,下面我列出一些资料供你参考。
上面是Silverlight实现的方案和资料。这篇文章是用WPF+WCF去实现的。列出Silerlight是方便大家有个对照。
视频会话实现的方式和语音通话实现的方式是一样的。他们之间不一样的地方在于,一个是通过麦克风获取数据,一个是通过摄像头获取数据。下面我用WF4画了一个流程图(这个流程图只是为了说明问题,没有用到程序里面)。
实现
前面说到了,WPF中没有像Silerlight一样集成了摄像的功能,在WPF中又如何去实现摄像呢?这也是首先要解决的问题,我经过一番google,在Codeplex上找到了一个开源WPF的Webcam控件。地址是:WebCam control for WPF。
添加一个窗体,在这个窗体上使用这个控件,布局如下。
注意:左边是本机的视频,右边是对方的视频。修改窗体的构造函数;
private IPEndPoint _serverEndPoint;
private UdpClient _socket;
public WebcamPlayerForm(IPEndPoint serverEndpoint, string caller, string callee)
{
}
与语音聊天一样,数据传递我使用了UdpClient,我感觉UdpClient简单好用。_serverEndPoint是WCF服务的地址,_socket用于视频数据传递。在客户端我使用了两个System.Windows.Threading.DispatcherTimer,本来打算直接使用两个线程,发现一些莫名奇妙的线程问题。两个DispatcherTimer,一个用来启动接受来自WCF服务的视频数据,一个用来将自己的视频数据发送到WCF服务。代码如下:
System.Windows.Threading.DispatcherTimer myDispatcherTimer = new System.Windows.Threading.DispatcherTimer();
myDispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
myDispatcherTimer.Tick += new EventHandler(captureVideo);
myDispatcherTimer.Start();
System.Windows.Threading.DispatcherTimer myDispatcherTimer2 = new System.Windows.Threading.DispatcherTimer();
myDispatcherTimer2.Interval = new TimeSpan(0, 0, 0, 0, 1000);
myDispatcherTimer2.Tick += new EventHandler(playVideo);
myDispatcherTimer2.Start();
captureVideo用于从摄像头捕获数据通过UdpClient发送到WCF服务中,代码如下。
private void captureVideo(object sender, EventArgs e)
{
try
{
byte[] bytes;
if (webcamPlayer.CurrentBitmap != null)
{
bytes = ConvertImageSourceToByteArray(webcamPlayer.CurrentBitmap);//webcamPlayer.CurrentBitmap
_socket.Send(bytes, bytes.Length, _serverEndPoint);
}
}
catch (Exception) { }
}
上面的captureVideo方法将视频数据先转发到WCF服务,在由WCF服务转发给对方,在WCF服务中有一个UdpClient接受数据,方法是listen(),它的代码如下:
private void listen()
{
try
{
while (true)
{
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
//if (sender.ToString() != "0.0.0.0:0")
//{
byte[] received = UdpListener.Receive(ref sender);
if (!_users.Contains(sender))
{
_users.Add(sender);
}
foreach (IPEndPoint endpoint in _users)
{
if (!endpoint.Equals(sender))
{
_udpSender.Send(received, received.Length, endpoint);
}
}
//}
}
}
catch (Exception e)
{
}
}
WCF服务中的listen()方法将接收到的数据发送给对方的客户端,在客户端有playVideo方法来接收和并播放来自WCF的视频数据,代码如下:
private void playVideo(object sender, EventArgs e)
{
try
{
lock (_socket)
{
if (_socket.Available != 0)
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 0);
byte[] received = _socket.Receive(ref endpoint);
image1.Source = ConvertByteArrayToImageSource(received);
}
}
}
catch
{
}
}
由于从摄像头获取的数据格式是ImageSource,我们需要将它转换成byte[]传输,转换的代码如下:
///
/// Converts an to an array of bytes.
///
/// to convert.
/// Array of bytes.
public byte[] ConvertImageSourceToByteArray( ImageSource image)
{
// Declare variables
byte[] result = null;
// Use a memory stream to convert
using (MemoryStream memoryStream = new MemoryStream())
{
// Get right encoder
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
// Get right frame
if (image is BitmapSource)
{
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)image));
}
// Now set some encoder values
encoder.QualityLevel = 100;
encoder.Save(memoryStream);
// Now convert
result = memoryStream.ToArray();
}
// Return result
return result;
}
从WCF服务收到到的数据是byte[] 格式,我们需要将其转换成ImageSource,代码如下:
///
/// Converts an array of bytes to a .
///
/// Bytes to convert.
/// .
public ImageSource ConvertByteArrayToImageSource(byte[] bytes)
{
// Declare variables
ImageSource result = null;
// Validate input
if (bytes.Length == 0) return null;
// Create memory stream - it seems that if you clean up or dispose
// the memory stream, you cannot display the image any longer
MemoryStream memoryStream = new MemoryStream(bytes);
// Assign to bitmap image
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
// Assign bitmap to image source
result = bitmapImage;
// Return result
return result;
}
在前面文章的的基础上完成这些操作,我们就可以实现视频会话的功能。
效果:
1、选择跟小花视频:
2、小花接受到请求:
3、视频中:
上图是我在一台电脑上演示的,所以只有一边显示数据。但是,我用两台笔记本测试过,效果也还不错。
总结:
主要用到的技术有;WCF、WPF、UDPClient。还使用了一个开源的控件WebCam control for WPF。这个程序调试了我一天的时间。
由于博客的空间不够用,过段时间整理好,会将代码上传到Codeplex上。
相关文章:
(全文完)
以下为广告部分
您部署的HTTPS网站安全吗?
如果您想看下您的网站HTTPS部署的是否安全,花1分钟时间来 myssl.com 检测以下吧。让您的HTTPS网站变得更安全!
快速了解HTTPS网站安全情况。
安全评级(A+、A、A-...)、行业合规检测、证书信息查看、证书链信息以及补完、服务器套件信息、证书兼容性检测等。
安装部署SSL证书变得更方便。
SSL证书内容查看、SSL证书格式转换、CSR在线生成、SSL私钥加解密、CAA检测等。
让服务器远离SSL证书漏洞侵扰
TLS ROBOT漏洞检测、心血漏洞检测、FREAK Attack漏洞检测、SSL Poodle漏洞检测、CCS注入漏洞检测。
wpf 语音通话_WPF+WCF一步一步打造音频聊天室(四):视频会话相关推荐
- wpf 语音通话_WPF+WCF一步一步打造音频聊天室(二):文字聊天和白板共享
这篇文章将讲述实现WPF的UI和WCF中的双工通信.实现文字部分的聊天功能和实现共享白板的功能. 画WPF的界面其实是一件麻烦的事情.虽然WPF和WindowsForm一样,能将控件拖到哪,它就在哪. ...
- wpf 语音通话_WPF+WCF一步一步打造音频聊天室(三):语音聊天
前一篇文章中实现了文字聊天和共享白板的功能,这篇文章中,我将在前一篇文章的基础上实现语音聊天的功能.语音聊天要比文字聊天和共享白板难度要大一点. 实现的大概的流程为: 1.一个聊天室成员向另外一个成员 ...
- WPF+WCF一步一步打造音频聊天室(三):语音聊天
前一篇文章中实现了文字聊天和共享白板的功能,这篇文章中,我将在前一篇文章的基础上实现语音聊天的功能.语音聊天要比文字聊天和共享白板难度要大一点. 实现的大概的流程为: 1.一个聊天室成员向另外一个成员 ...
- WPF+WCF一步一步打造音频聊天室(一):概述
前几天在老徐的MSN群中聊WCF.我突然想到了用WPF和WCF来打造音频聊天室这么一个轮子.其实是这样的,我在的公司是两岸三地合作开发的.两岸是指大陆和台湾,三地是指深圳.台北.高雄.由于公司很小,所 ...
- WPF+WCF一步一步打造音频聊天室(二):文字聊天和白板共享
这篇文章将讲述实现WPF的UI和WCF中的双工通信.实现文字部分的聊天功能和实现共享白板的功能. 画WPF的界面其实是一件麻烦的事情.虽然WPF和WindowsForm一样,能将控件拖到哪,它就在哪. ...
- 微信语音麦克风静音_微信正在语音通话的时候我按了静音,然后用手机看视频对方能听见吗?...
展开全部 这种情况对方是听不到的,送话器和扬声器都在被微信暂e68a84e8a2ad3231313335323631343130323136353331333433643733用. 语音通话是通过语音 ...
- wpf 语音通话_WPF---语音合成与语音识别
windows vista 和windows 7语音识别功能相关简介: 相信用过windows vista 和windows 7的人都知道或者了解过里面的语音识别功能.它可以使用声音命令来控制电脑,实 ...
- 只需五步,快速构建Python聊天室
在本文中,我们来谈一谈如何构建一个Python聊天室. 注意:你不需要安装任何额外的Python包. 作者 | Dark Soulz 译者 | 弯月,责编 | 郑丽媛 头图 | CSDN 下载自东方 ...
- html怎么能调用微信语音,华为微信的语音通话怎么录音
在用手机打电话时,如果我们想保留通话内容,会启用录音功能将其录制下来.现在很多人直接用微信进行语音通话,那华为微信的语音通话怎么录音? 华为微信的语音通话怎么录音? 以荣耀20s MagicUI2.1 ...
- 抓住语音社交风口,1天快速搭建语音聊天室
语音聊天室孵化 一起KTV.众人大合唱.语音开黑.狼人杀.剧本杀.多人配音.观影.语音电台.相亲联谊社交等,一般都是在语音聊天室中进行,那么语音聊天室产品如此火热的原因有哪些呢? 一对一社交适用于朋友 ...
最新文章
- 【风控策略】(未完成)策略规则与模型评分
- Stream流终结操作方法
- USB摄像头视频监控项目学习笔记
- (前端)html与css css 15、标准文档流
- Java面试题详解二:java中的关键字
- oracle连接实例怎么连接,连接ORACLE实例
- 10个资源满满的网站,偷偷收藏起来吧!
- Java调用第三方http接口的方式
- 高一计算机组装与维护教学总结,计算机优秀个人教学总结
- gitlab 报错500问题
- 计算机无法从usb启动不了,主板不能从u盘启动怎么办
- 数据库系统实践 III 查询语句
- python-控制键盘鼠标
- Linux基本命令---2
- Docker -v 对挂载的目录没有权限 Permission denied解决办法
- 软件设计的七大原则 --开闭原则 里氏替换原则 依赖倒置原则
- 树莓派科学小实验4B--07_继电器
- 利用PS调整图片文件的色彩饱和度
- 数字基建-高速公路智慧建造管控平台
- 大学生学完python靠几个接单网站兼职,实现经济独立
热门文章
- 老米之家 抢注域名应该怎么抢?抢注域名的价值如何去衡量
- 集成Ueditor秀米
- oracle查看视图定义语句_Oracle-视图
- 在线合并、分解PDF;PDF格式转换
- mysql的in能超过1000吗_SQL使用IN参量不能超过1000的表现形式以及解决办法
- python-获取图片的exif信息
- 12款华丽的Admin管理后台模板
- 识别到硬盘 计算机不显示盘符,Win10系统下移动硬盘可以识别但是不显示盘符的解决方法...
- VLAN隔离葵花宝典(一)
- ZIP RAR文件密码破解软件ARCHPR Pro4.54(绿色中文破解版)