C# 网络视频的问题 最近要做一个通过局域网,进行网络视频的功能开发,之前没有接触过这方面的东西,所以想这里问一下,有没有相关的开源的控件可以用? 在线等~谢谢. 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你需要研究三个东西,一个是TCP/UDP的socket编程,一个是directshow的api,以及视频编解码。 那这个directshow 是开源的吗? 有现成动态库。底层的是微软公司的产品,完全免费的。现在有C#版的directshow,就是封装了微软的类库了。 最简单的:用微软的DShow或者DirectX AuvioVideoPlayBack开发播放器,播放器根据服务器记录的播放文件路径和播放时间播放视频就可以了。附我项目的部分源码:播放器部分:using System;using System.Collections.Generic;using System.Collections;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Xml;using System.Xml.Linq;using System.Net;using Microsoft.DirectX.AudioVideoPlayback;using System.Threading;namespace stlive{ public partial class streamplayer : Form { //directx版 private Video video=null; //主播 private Audio audio=null; private Video video1=null; //备播 private Audio audio1=null; private Video timing_video = null; //定时播放 private Audio timing_audio = null; private int currentIndex = 0; //播放列表播放位置 private double pauseduration = 0; //当插播定时播放的直播流时,记录当前播放的视频的位置,以恢复播放用 private bool PrimaryVideoPlaying = true; //判断主播备播 private string playlist = string.Empty; //播放列表总表 public ArrayList pl=new ArrayList(); //将播放列表文件分离出来保存为独立文件名的列表数组 private string play_playpath = string.Empty, play_playtime = string.Empty, play_stoptime = string.Empty; private string[] str_date,str_time; //根据获取的当前日期时间构造符合规则的日期时间 private string timing_date=string.Empty,timing_time=string.Empty,timer4_timing_time=string.Empty,timing_stoptime=string.Empty; //符合规则的日期时间 //全局变量:播放列表 private string playlistselectstring, timing_playlistselectstring; //全局变量:系统配置相关 private string streamserverip,fileserverconnstr,ch1, ch2, ch3, ch4, ch5, stfont,stfontcolor,stbgcolor,stbgheight; private int ledw, ledh, ledx, ledy; //定义播放器状态全局变量 private string streamstatus = string.Empty; //定义播放器全局变量:每段广告滚动的次数。为了防止初始化失败,设置默认值为2 private int adroundnum=2; //定义字幕全局变量:滚动字幕 private string adtext = string.Empty; //定义公共属性:字幕开关状态 public string subtitlestatus { get; set; } //定义公共属性:本机的名字 public string pcname { get; set; } //在构造函数中初始化频道等信息 public streamplayer() { //开始构造窗体 InitializeComponent(); //取消对托管代码的管理 streamplayer.CheckForIllegalCrossThreadCalls = false; } /// <summary> /// 定义窗体重绘方法,当用户修改了系统参数的时候窗体能够实时刷新 /// </summary> public void repaintform() { //读取频道参数 //设置字幕样式及颜色 //设置字幕 //根据参数重新绘制窗体大小 } //退出系统需要确认 //配置管理 private void btn_config_Click(object sender, EventArgs e) { config cfgfrm = new config(this); cfgfrm.ShowDialog(); } //显示播放器状态 /// <summary> /// 窗体加载时,调用一些默认属性和方法 /// </summary> public void streamplayer_Load(object sender, EventArgs e) { //根据配置重绘控件 repaintform(); //设定按钮颜色 chg_btn_color(btn_dianbo); timer6.Stop(); getplaylist(); //运行时读取列表 } //如果读取文件播放列表失败,那么让定时器每隔1秒重新读取数据库,否则使定时器停止 private void timer6_Tick(object sender, EventArgs e) { getplaylist(); } //DirectX版本:读取文件播放列表 public void getplaylist() { currentIndex = 0; pl.Clear(); playlistselectstring = "select * from playlist where charindex('"+pcname+"',pcname)>0 and DateDiff(n,'" + DateTime.Now.ToString() + "',exptime)>0 order by orderid asc,id desc"; using (SqlConnection conn = new SqlConnection(fileserverconnstr)) { conn.Open(); using (SqlCommand cmd = new SqlCommand(playlistselectstring, conn)) { SqlDataReader dr = cmd.ExecuteReader(); while (dr.Read()) { pl.Add(dr["filepath"].ToString()); } dr.Close(); } conn.Close(); conn.Dispose(); } if (pl.Count > 0) { timer6.Stop(); playstream(pl[currentIndex].ToString()); } else { timer6.Start(); } } //DirectX版本:播放列表具体文件 private void playstream(string fileName) { int height; int width; fileName = fileName.ToLower(); try { if (PrimaryVideoPlaying) { height = panel1.Height; width = panel1.Width; PrimaryVideoPlaying = false; if (audio1 != null) { audio1.Dispose(); audio1 = null; } if (video1 != null) { video1.Dispose(); video1 = null; } video1 = Video.FromFile(fileName); audio1 = video1.Audio; audio1.Volume = 0; //音量最大 audio1.Balance = 0; //声道平衡 video1.HideCursor(); lbl_playerstatus.Text = fileName; panel1.Height = height; panel1.Width = width; video1.Owner = panel1; if (pauseduration > 0) { video1.CurrentPosition = pauseduration; pauseduration = 0; } video1.Play(); timer1.Start(); } else { height = panel1.Height; width = panel1.Width; PrimaryVideoPlaying = true; if (audio != null) { audio.Dispose(); audio = null; } if (video != null) { video.Dispose(); video = null; } video = Video.FromFile(fileName); audio = video.Audio; audio.Volume = 0; //音量最大 audio.Balance = 0; //声道平衡 video.HideCursor(); lbl_playerstatus.Text = fileName; panel1.Height = height; panel1.Width = width; video.Owner = panel1; if (pauseduration > 0) { video.CurrentPosition = pauseduration; pauseduration = 0; } video.Play(); timer.Start(); } } catch { jumperrthenplaynext(); } } //播放video的计时器 private void timer_Tick(object sender, EventArgs e) {} private void timer1_Tick(object sender, EventArgs e) { } //DirectX版本:如果遇到错误,尝试跳过错误继续播放 private void jumperrthenplaynext() { disposeplayer(); //向服务器报告错误 string cmdstr = "insert into buginfo(pcname,buginfo) values('"+pcname+"','播放视频失败,文件不存在或无该视频格式的解码器:"+pl[currentIndex].ToString()+"')"; using (SqlConnection conn = new SqlConnection(fileserverconnstr)) { conn.Open(); using (SqlCommand cmd = new SqlCommand(cmdstr, conn)) { cmd.ExecuteNonQuery(); } conn.Close(); conn.Dispose(); } currentIndex = (currentIndex + 1) % pl.Count; //当一个列表循环结束后,更新一下列表以检查是否有新视频加入 if (currentIndex == 0) { getplaylist(); } else { playstream(pl[currentIndex].ToString()); } } //释放播放器占用的所有资源 public void disposeplayer() {} //选择文件点播 private void btn_all_Click(object sender, EventArgs e) {} //频道选择,选择流媒体直播 //设定按钮颜色 private void chg_btn_color(Button btn_name) { } //字幕管理 /// <summary> /// 定义公共方法:开关字幕;供subtitle窗体调用 /// </summary> private void opensubtitle() { scrollingText1.Enabled = true; scrollingText1.Visible = true; } private void closesubtitle() { scrollingText1.Enabled = false; scrollingText1.Visible = false; } private void 关于ToolStripMenuItem_Click(object sender, EventArgs e) { about aboutfrm = new about(); aboutfrm.Show(); } private void tp_openlist_Click(object sender, EventArgs e) { //打开定时播放列表窗体 timingplaylistform tpl_frm = new timingplaylistform(this); tpl_frm.Show(); } private void tp_closeplaylist_Click(object sender, EventArgs e) { Application.OpenForms["timingplaylistform"].Dispose(); } } }} 服务器端添加视频部分:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Xml;using System.Drawing;using System.Text;using System.Windows.Forms;using System.IO;namespace stserver{ public partial class addvideo : Form { playlist ps = new playlist(); public addvideo(playlist frm_ps) { ps = frm_ps; InitializeComponent(); } //数据库连接字符串 public string connstr = string.Empty; //定义全局变量,获得的文件的列表 public string filenames=string.Empty; //定义全局变量,屏幕分组属性 private string pcname=string.Empty; private bool cb_all_ischecked = false; private void btn_caiji_Click(object sender, EventArgs e) { filenames = ""; OpenFileDialog ofd = new OpenFileDialog(); ofd.Multiselect = true; ofd.Filter = "视频文件(*.mpg,*.wmv,*.avi)|*.mpg;*.wmv;*.avi"; if (DialogResult.OK == ofd.ShowDialog()) { tb_filename.Text = ""; for (int i = 0; i < ofd.FileNames.Length; i++) { tb_filename.Text += ofd.FileNames[i].ToString()+"\n"; //构造共数据库使用的文件名串 filenames += ofd.FileNames[i].ToString() + "|"; } } } private void btn_update_Click(object sender, EventArgs e) { pcname = pcname.Substring(0, pcname.Length - 1); SqlConnection conn = new SqlConnection(connstr); conn.Open(); SqlCommand cmd = new SqlCommand(); cmd.Connection = conn; //分割数组,构造文件路径名 //MessageBox.Show(filenames); //filenames = filenames.Replace('\\', '/'); string[] array_fname = filenames.Split('|'); for (int i = 0; i < array_fname.Length - 1; i++) { string[] array_fpath = array_fname[i].Split(':'); //DEBUG分割的信息是否正确 //MessageBox.Show("路径:"+array_fpath[1]+" 文件名:"+Path.GetFileName(array_fpath[1])); cmd.CommandType = CommandType.Text; cmd.CommandText = @"insert into playlist(filepath,filename,pcname,exptime) values('\\192.168.2.253\d$" + array_fpath[1] + "','" + Path.GetFileName(array_fpath[1]) + "','" + pcname + "','" + DateTime.Now.AddDays((int)dayofplay.Value).ToString() + "')"; int j = cmd.ExecuteNonQuery(); if (j < 1) { MessageBox.Show("错误!添加播放列表失败!\n\n数据库可能正忙,请稍后再试\n\n如果再次尝试不能解决问题,请联系技术部", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); break; } } conn.Close(); conn.Dispose(); //filenames全局变量再次初始化 filenames = ""; pcname = string.Empty; if (DialogResult.No == MessageBox.Show("视频采集成功!\n\n是否留在该页面继续采集?", "成功", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) { ps.bind(); this.Close(); } else { ps.bind(); tb_filename.Text = ""; } } private void addvideo_Load(object sender, EventArgs e) { XmlDocument doc = new XmlDocument(); doc.Load(Application.StartupPath+"\\config.xml"); connstr = doc.DocumentElement.SelectSingleNode("serverconnstr").InnerText; } private void button1_Click(object sender, EventArgs e) { ps.bind(); this.Close(); } private void cb_all_CheckedChanged(object sender, EventArgs e) {} }} 前后台核心代码都给你贴上了,自己参考简单修改一下就能够使用了。这是最简单的,通过局域网IP进行播放,服务器端进行视频采集,就是将视频文件的路径记录到服务器中,客户端播放时从服务器提起视频路径进行播放即可。还有一种更方便的方法是使用QVOD播放组件进行二次开发,QVOD组件是专门供局域网视频播放开发用的。你可以到QVOD官方论坛去,讨论这个开发的不少,而且有不少在线视频点播也是用QVOD开发的,更别说网吧了,QVOD有专门网吧服务器和二次开发组件 C#如何实现输入框光标闪动的效果 C#调用C++DLL问题,全分投入求大侠指点 datagraview 读文本文件的内容的问题 winform关于控件数组的问题 C#,如何获取30天之前的时间。 大家一起来找碴,这两个结构体,有什么不多。 关于picturebox画图 C#高级编程里不懂的地方,50分 求:《人月传说》的下载地址 自定义控件如何使用设定的属性? 未能加载文件或程序集“System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken 未将对象引用到对象实例中
那这个directshow 是开源的吗?
现在有C#版的directshow,就是封装了微软的类库了。
用微软的DShow或者DirectX AuvioVideoPlayBack开发播放器,播放器根据服务器记录的播放文件路径和播放时间播放视频就可以了。附我项目的部分源码:
播放器部分:using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Net;
using Microsoft.DirectX.AudioVideoPlayback;
using System.Threading;namespace stlive
{
public partial class streamplayer : Form
{
//directx版
private Video video=null; //主播
private Audio audio=null;
private Video video1=null; //备播
private Audio audio1=null;
private Video timing_video = null; //定时播放
private Audio timing_audio = null;
private int currentIndex = 0; //播放列表播放位置
private double pauseduration = 0; //当插播定时播放的直播流时,记录当前播放的视频的位置,以恢复播放用
private bool PrimaryVideoPlaying = true; //判断主播备播
private string playlist = string.Empty; //播放列表总表
public ArrayList pl=new ArrayList(); //将播放列表文件分离出来保存为独立文件名的列表数组
private string play_playpath = string.Empty, play_playtime = string.Empty, play_stoptime = string.Empty;
private string[] str_date,str_time; //根据获取的当前日期时间构造符合规则的日期时间
private string timing_date=string.Empty,timing_time=string.Empty,timer4_timing_time=string.Empty,timing_stoptime=string.Empty; //符合规则的日期时间
//全局变量:播放列表
private string playlistselectstring, timing_playlistselectstring;
//全局变量:系统配置相关
private string streamserverip,fileserverconnstr,ch1, ch2, ch3, ch4, ch5, stfont,stfontcolor,stbgcolor,stbgheight;
private int ledw, ledh, ledx, ledy;
//定义播放器状态全局变量
private string streamstatus = string.Empty;
//定义播放器全局变量:每段广告滚动的次数。为了防止初始化失败,设置默认值为2
private int adroundnum=2;
//定义字幕全局变量:滚动字幕
private string adtext = string.Empty;
//定义公共属性:字幕开关状态
public string subtitlestatus
{
get;
set;
} //定义公共属性:本机的名字
public string pcname
{
get;
set;
}
//在构造函数中初始化频道等信息
public streamplayer()
{
//开始构造窗体
InitializeComponent();
//取消对托管代码的管理
streamplayer.CheckForIllegalCrossThreadCalls = false;
} /// <summary>
/// 定义窗体重绘方法,当用户修改了系统参数的时候窗体能够实时刷新
/// </summary>
public void repaintform()
{
//读取频道参数 //设置字幕样式及颜色
//设置字幕
//根据参数重新绘制窗体大小
}
//退出系统需要确认
//配置管理
private void btn_config_Click(object sender, EventArgs e)
{
config cfgfrm = new config(this);
cfgfrm.ShowDialog();
} //显示播放器状态 /// <summary>
/// 窗体加载时,调用一些默认属性和方法
/// </summary>
public void streamplayer_Load(object sender, EventArgs e)
{
//根据配置重绘控件
repaintform(); //设定按钮颜色
chg_btn_color(btn_dianbo); timer6.Stop();
getplaylist(); //运行时读取列表 } //如果读取文件播放列表失败,那么让定时器每隔1秒重新读取数据库,否则使定时器停止
private void timer6_Tick(object sender, EventArgs e)
{
getplaylist();
}
//DirectX版本:读取文件播放列表
public void getplaylist()
{
currentIndex = 0;
pl.Clear();
playlistselectstring = "select * from playlist where charindex('"+pcname+"',pcname)>0 and DateDiff(n,'" + DateTime.Now.ToString() + "',exptime)>0 order by orderid asc,id desc";
using (SqlConnection conn = new SqlConnection(fileserverconnstr))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(playlistselectstring, conn))
{
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
pl.Add(dr["filepath"].ToString());
}
dr.Close();
}
conn.Close();
conn.Dispose();
}
if (pl.Count > 0)
{
timer6.Stop();
playstream(pl[currentIndex].ToString());
}
else
{
timer6.Start();
}
} //DirectX版本:播放列表具体文件
private void playstream(string fileName)
{
int height;
int width;
fileName = fileName.ToLower();
try
{
if (PrimaryVideoPlaying)
{
height = panel1.Height;
width = panel1.Width;
PrimaryVideoPlaying = false;
if (audio1 != null)
{
audio1.Dispose();
audio1 = null;
}
if (video1 != null)
{
video1.Dispose();
video1 = null;
}
video1 = Video.FromFile(fileName);
audio1 = video1.Audio;
audio1.Volume = 0; //音量最大
audio1.Balance = 0; //声道平衡
video1.HideCursor();
lbl_playerstatus.Text = fileName;
panel1.Height = height;
panel1.Width = width;
video1.Owner = panel1;
if (pauseduration > 0)
{
video1.CurrentPosition = pauseduration;
pauseduration = 0;
}
video1.Play();
timer1.Start();
}
else
{
height = panel1.Height;
width = panel1.Width;
PrimaryVideoPlaying = true;
if (audio != null)
{
audio.Dispose();
audio = null;
}
if (video != null)
{
video.Dispose();
video = null;
}
video = Video.FromFile(fileName);
audio = video.Audio;
audio.Volume = 0; //音量最大
audio.Balance = 0; //声道平衡
video.HideCursor();
lbl_playerstatus.Text = fileName;
panel1.Height = height;
panel1.Width = width;
video.Owner = panel1;
if (pauseduration > 0)
{
video.CurrentPosition = pauseduration;
pauseduration = 0;
}
video.Play();
timer.Start();
}
}
catch
{
jumperrthenplaynext();
}
} //播放video的计时器
private void timer_Tick(object sender, EventArgs e)
{}
private void timer1_Tick(object sender, EventArgs e)
{
} //DirectX版本:如果遇到错误,尝试跳过错误继续播放
private void jumperrthenplaynext()
{
disposeplayer();
//向服务器报告错误
string cmdstr = "insert into buginfo(pcname,buginfo) values('"+pcname+"','播放视频失败,文件不存在或无该视频格式的解码器:"+pl[currentIndex].ToString()+"')";
using (SqlConnection conn = new SqlConnection(fileserverconnstr))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(cmdstr, conn))
{
cmd.ExecuteNonQuery();
}
conn.Close();
conn.Dispose();
}
currentIndex = (currentIndex + 1) % pl.Count;
//当一个列表循环结束后,更新一下列表以检查是否有新视频加入
if (currentIndex == 0)
{
getplaylist();
}
else
{
playstream(pl[currentIndex].ToString());
}
} //释放播放器占用的所有资源
public void disposeplayer()
{}
//选择文件点播
private void btn_all_Click(object sender, EventArgs e)
{} //频道选择,选择流媒体直播
//设定按钮颜色
private void chg_btn_color(Button btn_name)
{
} //字幕管理
/// <summary>
/// 定义公共方法:开关字幕;供subtitle窗体调用
/// </summary>
private void opensubtitle()
{
scrollingText1.Enabled = true;
scrollingText1.Visible = true;
}
private void closesubtitle()
{
scrollingText1.Enabled = false;
scrollingText1.Visible = false;
} private void 关于ToolStripMenuItem_Click(object sender, EventArgs e)
{
about aboutfrm = new about();
aboutfrm.Show();
} private void tp_openlist_Click(object sender, EventArgs e)
{
//打开定时播放列表窗体
timingplaylistform tpl_frm = new timingplaylistform(this);
tpl_frm.Show();
} private void tp_closeplaylist_Click(object sender, EventArgs e)
{
Application.OpenForms["timingplaylistform"].Dispose();
} } }
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Xml;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace stserver
{
public partial class addvideo : Form
{
playlist ps = new playlist();
public addvideo(playlist frm_ps)
{
ps = frm_ps;
InitializeComponent();
} //数据库连接字符串
public string connstr = string.Empty;
//定义全局变量,获得的文件的列表
public string filenames=string.Empty;
//定义全局变量,屏幕分组属性
private string pcname=string.Empty;
private bool cb_all_ischecked = false;
private void btn_caiji_Click(object sender, EventArgs e)
{
filenames = "";
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
ofd.Filter = "视频文件(*.mpg,*.wmv,*.avi)|*.mpg;*.wmv;*.avi";
if (DialogResult.OK == ofd.ShowDialog())
{
tb_filename.Text = "";
for (int i = 0; i < ofd.FileNames.Length; i++)
{
tb_filename.Text += ofd.FileNames[i].ToString()+"\n";
//构造共数据库使用的文件名串
filenames += ofd.FileNames[i].ToString() + "|";
}
}
} private void btn_update_Click(object sender, EventArgs e)
{
pcname = pcname.Substring(0, pcname.Length - 1);
SqlConnection conn = new SqlConnection(connstr);
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
//分割数组,构造文件路径名
//MessageBox.Show(filenames);
//filenames = filenames.Replace('\\', '/');
string[] array_fname = filenames.Split('|'); for (int i = 0; i < array_fname.Length - 1; i++)
{
string[] array_fpath = array_fname[i].Split(':');
//DEBUG分割的信息是否正确
//MessageBox.Show("路径:"+array_fpath[1]+" 文件名:"+Path.GetFileName(array_fpath[1]));
cmd.CommandType = CommandType.Text;
cmd.CommandText = @"insert into playlist(filepath,filename,pcname,exptime) values('\\192.168.2.253\d$" + array_fpath[1] + "','" + Path.GetFileName(array_fpath[1]) + "','" + pcname + "','" + DateTime.Now.AddDays((int)dayofplay.Value).ToString() + "')";
int j = cmd.ExecuteNonQuery();
if (j < 1)
{
MessageBox.Show("错误!添加播放列表失败!\n\n数据库可能正忙,请稍后再试\n\n如果再次尝试不能解决问题,请联系技术部", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
break;
}
}
conn.Close();
conn.Dispose();
//filenames全局变量再次初始化
filenames = "";
pcname = string.Empty;
if (DialogResult.No == MessageBox.Show("视频采集成功!\n\n是否留在该页面继续采集?", "成功", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
{
ps.bind();
this.Close();
}
else
{
ps.bind();
tb_filename.Text = "";
}
} private void addvideo_Load(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.Load(Application.StartupPath+"\\config.xml");
connstr = doc.DocumentElement.SelectSingleNode("serverconnstr").InnerText;
} private void button1_Click(object sender, EventArgs e)
{
ps.bind();
this.Close();
} private void cb_all_CheckedChanged(object sender, EventArgs e)
{} }
}
还有一种更方便的方法是使用QVOD播放组件进行二次开发,QVOD组件是专门供局域网视频播放开发用的。你可以到QVOD官方论坛去,讨论这个开发的不少,而且有不少在线视频点播也是用QVOD开发的,更别说网吧了,QVOD有专门网吧服务器和二次开发组件