试图通过 TCP 流式传输 2 路音频?
Posted
技术标签:
【中文标题】试图通过 TCP 流式传输 2 路音频?【英文标题】:Trying to stream 2 way audio over TCP? 【发布时间】:2013-12-08 19:27:33 【问题描述】:我正在尝试制作一个视频会议应用程序(用 c# 编写),它允许 2 个用户使用 TCP 进行视频会议。此外,用户可以单独进行文字聊天。现在,我有一个工作的视频流,但还没有音频工作。我不确定如何访问麦克风,使用 TCP 流式传输它,然后在其他用户的扬声器上播放它,因为我对 c# 相对较新,并且对使用媒体是全新的。
如果有人可以向我指出示例代码,请帮助我了解如何访问麦克风,或者您认为对我有帮助的任何其他内容,那就太好了。
我按原样附上我的代码以供参考。
WEBCAM.cs
using System;
using System.IO;
using System.Linq;
using System.Text;
using WebCam_Capture;
using System.Windows.Controls;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Net;
using System.Net.Sockets;
using System.Windows;
namespace DuckTalk
class WebCam
const int TEXT_VIDEO_NUM = 45674;
private System.Windows.Controls.TextBox _hostIpAddressBox;
private WebCamCapture webcam;
private int FrameNumber = 30;
public void InitializeWebCam(ref System.Windows.Controls.TextBox hostIpAddressBox)
webcam = new WebCamCapture();
webcam.FrameNumber = ((ulong)(0ul));
webcam.TimeToCapture_milliseconds = FrameNumber;
webcam.ImageCaptured += new WebCamCapture.WebCamEventHandler(webcam_ImageCaptured);
_hostIpAddressBox = hostIpAddressBox;
void webcam_ImageCaptured(object source, WebcamEventArgs e)
TcpClient connection = null;
NetworkStream stream = null;
byte[] imgBytes;
try
//Set up IPAddress
IPAddress ipAddress = IPAddress.Parse(_hostIpAddressBox.Text);
IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, TEXT_VIDEO_NUM);
//Connect to TCP
connection = new TcpClient();
connection.Connect(ipLocalEndPoint);
// Get a client stream for reading and writing.
stream = connection.GetStream();
//Send image as bytes
imgBytes = ImageByteConverter.ImageToBytes((System.Drawing.Bitmap)e.WebCamImage);
stream.Write(imgBytes, 0, imgBytes.Length);
catch (Exception error)
MessageBox.Show("ERROR: " + error.Message);
finally
// Close everything.
if (connection != null)
connection.Close();
if (stream != null)
stream.Close();
public void Start()
webcam.TimeToCapture_milliseconds = FrameNumber;
webcam.Start(0);
public void Stop()
webcam.Stop();
ImageByteConverter.cs
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
namespace DuckTalk
class ImageByteConverter
public static byte[] ImageToBytes(System.Drawing.Bitmap bitmap)
byte[] byteArray;
using (MemoryStream stream = new MemoryStream())
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Close();
byteArray = stream.ToArray();
return byteArray;
public static BitmapImage BytesToImage(byte[] imgBytes)
var image = new BitmapImage();
image.BeginInit();
image.StreamSource = new System.IO.MemoryStream(imgBytes);
image.EndInit();
return image;
Window1.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Net;
using System.Net.Sockets;
namespace DuckTalk
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class MainWindow : Window
const int TEXT_PORT_NUM = 45673;
const int TEXT_VIDEO_NUM = 45674;
WebCam webcam;
public MainWindow()
InitializeComponent();
private void mainWindow_Loaded(object sender, System.Windows.RoutedEventArgs e)
webcam = new WebCam();
webcam.InitializeWebCam(ref xaml_hostTextBox);
var _backgroundIMWorker = new BackgroundWorker();
var _backgroundVidWorker = new BackgroundWorker();
_backgroundIMWorker.WorkerReportsProgress = true;
_backgroundVidWorker.WorkerReportsProgress = true;
// Set up the Background Worker Events
_backgroundIMWorker.DoWork += new DoWorkEventHandler(keepListeningForInstantMessages);
_backgroundVidWorker.DoWork += new DoWorkEventHandler(keepListeningForVideoMessages);
// Run the Background Workers
_backgroundIMWorker.RunWorkerAsync();
_backgroundVidWorker.RunWorkerAsync();
///////////////////////////////////////////////////////////////////////////////////////////////
//
//
// The next 2 functions take care of the instant messaging part of the program
//
//
//
///////////////////////////////////////////////////////////////////////////////////////////////
private void keepListeningForInstantMessages(object sender, DoWorkEventArgs e)
Action<string> displayIncomingMessage = (incomingMsg) =>
xaml_incomingTextBox.Text += "\n\nINCOMING MESSAGE: " + incomingMsg;
xaml_incomingTextScroll.ScrollToBottom();
;
Socket connection;
Byte[] data;
String msg;
// create the socket
Socket listenSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
// bind the listening socket to the port
IPEndPoint ep = new IPEndPoint(IPAddress.Any, TEXT_PORT_NUM);
listenSocket.Bind(ep);
while (true)
msg = "";
data = new Byte[3000];
// start listening
listenSocket.Listen(1);
//Received a connection
connection = listenSocket.Accept();
//Get Data
connection.Receive(data);
//Get the message in string format
msg = System.Text.Encoding.Default.GetString(data);
msg = msg.Substring(0,msg.IndexOf((char)0));
//Send message to the UI
xaml_incomingTextBox.Dispatcher.BeginInvoke(displayIncomingMessage, msg);
connection.Close();
//end of keepListeningForInstantMessages
void SendInstantMsg(object sender, RoutedEventArgs e)
TcpClient connection = null;
NetworkStream stream = null;
byte[] data;
xaml_incomingTextBox.Text += "\n\nOUTGOING MESSAGE: " + xaml_outgoingTextBox.Text;
try
//Set up IPAddress
IPAddress ipAddress = IPAddress.Parse(xaml_hostTextBox.Text);
IPEndPoint ipLocalEndPoint = new IPEndPoint(ipAddress, TEXT_PORT_NUM);
//Connect to TCP
connection = new TcpClient();
connection.Connect(ipLocalEndPoint);
//Convert text to bytes
data = System.Text.Encoding.ASCII.GetBytes(xaml_outgoingTextBox.Text);
// Get a client stream for reading and writing.
stream = connection.GetStream();
// Send the message to the connected TcpServer.
stream.Write(data, 0, data.Count());
xaml_outgoingTextBox.Text = "";
catch (Exception error)
MessageBox.Show("ERROR: " + error.Message);
finally
// Close everything.
if (connection != null)
connection.Close();
if (stream != null)
stream.Close();
//end of SendInstantMsg
///////////////////////////////////////////////////////////////////////////////////////////////
//
//
// The next 2 functions take care of the video part of the program
//
//
//
///////////////////////////////////////////////////////////////////////////////////////////////
private void keepListeningForVideoMessages(object sender, DoWorkEventArgs e)
Action<Byte[]> displayIncomingVideo = (incomingImgBytes) =>
xaml_incomingVideo.Source = ImageByteConverter.BytesToImage(incomingImgBytes);
;
Socket connection;
Byte[] incomingBytes;
Byte[] data;
int offset;
int numOfBytesRecieved;
// create the socket
Socket listenSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
// bind the listening socket to the port
IPEndPoint ep = new IPEndPoint(IPAddress.Any, TEXT_VIDEO_NUM);
listenSocket.Bind(ep);
while (true)
offset = 0;
numOfBytesRecieved = -1;
incomingBytes = new Byte[300000];
// start listening
listenSocket.Listen(1);
//Received a connection
connection = listenSocket.Accept();
//Get all the data from the connection stream
while (numOfBytesRecieved != 0)
numOfBytesRecieved = connection.Receive(incomingBytes, offset, 10000, SocketFlags.None);
offset += numOfBytesRecieved;
data = new Byte[offset];
Array.Copy(incomingBytes, data, offset);
//Send image to the UI
xaml_incomingTextBox.Dispatcher.BeginInvoke(displayIncomingVideo, data);
connection.Close();
//end of keepListeningForVideoMessages
private void SendVideoMsg(object sender, RoutedEventArgs e)
xaml_incomingVideo.Visibility = Visibility.Visible;
xaml_StopVideoButton.Visibility = Visibility.Visible;
xaml_SendTextButton.Visibility = Visibility.Hidden;
webcam.Start();
private void StopVideoMsg(object sender, RoutedEventArgs e)
xaml_incomingVideo.Visibility = Visibility.Hidden;
xaml_StopVideoButton.Visibility = Visibility.Hidden;
xaml_SendTextButton.Visibility = Visibility.Visible;
webcam.Stop();
//end of Class
//end of NameSpace
【问题讨论】:
I'm relatively new to c# and brand new to using media
然后,我建议搜索一些库。从头开始编写它会很困难。
【参考方案1】:
您应该尝试下载 NAudio,它是一个开源音频库。它附带了一个演示如何使用 UDP 将音频从一台电脑传输到另一台电脑;它位于名为“网络聊天”的 NAudioDemo 应用程序中。
http://naudio.codeplex.com/
您当前使用的 TCP 并不真正推荐用于音频。改用 UDP
http://www.onsip.com/about-voip/sip/udp-versus-tcp-for-voip
或者,如果您不想重新发明***(我不确定您的项目的最终目标是什么),您可以尝试下载我们的 iConf.NET 视频会议 SDK,它可以为您完成大部分工作(但不是免费的)
http://avspeed.com/
【讨论】:
以上是关于试图通过 TCP 流式传输 2 路音频?的主要内容,如果未能解决你的问题,请参考以下文章
从 MIC 录制并流式传输到 TCP 服务器; MediaRecorder:启动失败:-38