直播視頻跨瀏覽器預覽方案(ffmpeg+VideoJS+H5)附原始碼
- 1.概述
- 2.前言
- 3.思路
- 4.詳解
- 4.1.ffmpeg
- 4.1.1.配置方法
- 4.1.2.驗證方法
- 4.1.3.啟動方法
- 4.1.3.1.手動啟動
- 4.1.3.2.代碼啟動
- 4.2.前端頁面
- 5.原始碼
- 6.轉載
1.概述
本文主要介紹一種在H5頁面中,跨瀏覽器預覽目前主流直播攝像頭使用的rtsp流的預覽方案,由于本人第一次接觸這類需求,所以只是做到功能完整,還有各種不足之處,望各位大神指正,
2.前言
目前直播攝像頭主要采用rtsp視頻流的方式進行傳輸,而rtsp流是無法直接被瀏覽器所加載的,之前常用的方式是通過VLC media player插件來對視頻進行預覽,但隨著時間的推移,VLC已經無法被大多數瀏覽器所兼容,所以無奈只能上網查找其他可以在瀏覽器直接瀏覽直播視頻的方式,(VLC兼容性),學習后做如下總結,留于有該類需求的小伙伴及自己查看使用,
3.思路
既然已經知道直播攝像頭所采用的rtsp視頻流無法直接被進行加載,那擺在我們面前的就只有幾條路可以走,
1.自己獨立開發rtsp流的解碼及播放功能,
2.將rtsp流想辦法處理為可以被瀏覽器所支持的視頻流格式,
3.更換攝像頭,,,(完全不現實,甲方不會允許的)
饒小弟才疏學淺,對視頻流方面的涉獵真心不多,無奈只能選擇第二條路,于是就有了如下的解決方案,
服務端:
第一、需要對rtsp的直播流實時進行轉換,將其轉換為可以被瀏覽器播放的其他視頻流,
第二、需要在將轉換后的視頻流推送給客戶端,
第三、當客戶端關閉視頻預覽后,需要同時洗掉轉換后的視頻流檔案及關閉服務端對應的視頻轉換行程,
客戶端:
第一、將視頻需要的用戶名等資訊傳遞到服務器,用于生成rtsp視頻流,(我的程式是從前臺讀取的登錄資訊,也可以直接在后臺從資料庫中查詢)
第二、將服務端轉換好的視頻流加載入頁面,
第三、需要考慮視頻在頁面中加載時對瀏覽器的通用性,
第四、將關閉視頻的信號發送回服務端,使其釋放視瞥澩,
4.詳解
4.1.ffmpeg
FFmpeg是一套可以用來記錄、轉換數字音頻、視頻,并能將其轉化為流的開源計算機程式(下載),
之所以選擇用FFmpeg原因有三:一是因為其開源且免費(特別重要),二是因為功能比較全面,三是因為使用人數較多,網上的貼子也別較多,遇到問題比較容易查找解決,
4.1.1.配置方法
下載好對應版本的ffmpeg應用包,進行解壓,解壓后包含bin和doc兩個檔案夾,其中doc檔案夾為使用demo及一些說明,bin檔案夾則為需要用到的內容,包括ffmpeg.exe、ffplay.exe、ffprobe.exe三個檔案,
解壓后無需安裝,只需要在環境變數中添加好地址即可,方法:我的電腦----右鍵"屬性" —選擇 “高級系統屬性”----在“環境變數”中的【PATH】追加路徑 (剛剛解壓bin檔案夾路徑),重啟電腦即可,例如我的就解壓在“E:\HKVideoDemo\ffmpegToHLS\ffmpeg-w64\bin;”
4.1.2.驗證方法
在運行視窗(Win+R)中,輸入CMD,輸入ffmpeg回車即可看到如下內容,
4.1.3.啟動方法
4.1.3.1.手動啟動
在運行視窗(Win+R)中,輸入ffmpeg -i 直播攝像頭rtsp流資訊 其他ffmpeg引數即可,
附:
rtsp直播流獲取方式 rtsp://視頻用戶名:視頻密碼@視頻IP地址:埠號(默認554)/碼率/通道號/main/av_stream
ffmpeg完成命令配置拼接 ffmpeg -i rtsp://視頻用戶名:視頻密碼@視頻IP地址:埠號(默認554)/碼率/通道號/main/av_stream -fflags flush_packets -max_delay 1 -an -flags -global_header -hls_time 1 -hls_list_size 3 -hls_wrap 3 -vcodec copy -y 轉換后輸出hls流的地址
具體ffmpeg的各引數說明在此就不詳細敘述了,想了解的同學可以參考(ffmpeg引數說明)
4.1.3.2.代碼啟動
上述啟動方式需要先手動在命令視窗將ffmpeg命令運行起來,如果需要同時查看多個直播視頻,則需要運行多個命令視窗,非常不便于操作,于是我通過C#的行程啟動方式將其進行了代碼化,直接上代碼:
/// <summary>
/// 播放
/// </summary>
/// <param name="param">前臺傳過來的視頻用戶名等資訊</param>
private void videoPlay(string param)
{
if (!string.IsNullOrEmpty(param))
{
CloseProessAndDelFile();//結束正在運行的行程
string _HLSFileName = Guid.NewGuid().ToString(); //轉換名稱可以隨便起,停止的時候帶回去用于洗掉檔案
VideoInfo vi = JsonConvert.DeserializeObject<VideoInfo>(param);
vi.HLSFileName = _HLSFileName;
Session["_VideoInfo"] = vi; //Session變數存盤視頻資訊
if (Directory.Exists(vi.HLSPath) == false)//如果不存在就創建file檔案夾
{
Directory.CreateDirectory(vi.HLSPath);
}
#region 啟動ffmpeg服務
//拼接命令
string strML = "-i";
strML += " rtsp://" + vi.username + ":" + vi.password + "@" + vi.ip + ":" + vi.port + "/H.264/ch1/main/av_stream";
strML += " -fflags flush_packets";
strML += " -max_delay 1";
strML += " -an";
strML += " -flags";
strML += " -global_header";
strML += " -hls_time 1";
strML += " -hls_list_size 3";
strML += " -hls_wrap 3";
strML += " -vcodec copy";
strML += " -y";
strML += " "+vi.HLSPath;
strML += vi.HLSFileName+ ".m3u8";
ExcuteProcess("ffmpeg.exe", strML, (s, e) => Console.WriteLine(e.Data));
#endregion
while (Session["_ProcessID"] != null)
{
Thread.Sleep(3000);//啟動轉換服務后,形成流檔案需要一點時間,所以先暫停,時間根據實際情況設定
//向客戶端寫回資料
Response.ContentType = "text/plain";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.Write(vi.HLSFileName);
Response.End();
}
}
}
/// <summary>
/// 啟動行程
/// </summary>
/// <param name="exe">啟動程式行程名</param>
/// <param name="arg">啟動引數</param>
/// <param name="output">輸出</param>
private void ExcuteProcess(string exe, string arg, DataReceivedEventHandler output)
{
var p = new Process();
p.StartInfo.FileName = exe;
p.StartInfo.Arguments = arg;
p.StartInfo.UseShellExecute = false; //輸出資訊重定向
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;
p.OutputDataReceived += output;
p.ErrorDataReceived += output;
p.Start(); //啟動執行緒
p.BeginOutputReadLine();
p.BeginErrorReadLine();
Session["_ProcessID"] = p.Id; //存盤啟動的行程ID
//p.WaitForExit(); //等待行程結束
}
/// <summary>
/// 判斷 關閉行程并洗掉檔案
/// </summary>
private string CloseProessAndDelFile() {
string FileName = "";
#region 判斷并關閉已經開啟的轉換行程
if (Session["_ProcessID"] != null)
{
//根據行程ID,關閉行程
Process[] processes = System.Diagnostics.Process.GetProcesses();
foreach (Process item in processes)
{
if (item.Id == int.Parse(Session["_ProcessID"].ToString()))
{
item.Kill();
break;
}
}
}
#endregion
#region 洗掉視頻流檔案
if (Session["_VideoInfo"] != null)
{
VideoInfo vi = Session["_VideoInfo"] as VideoInfo;
//需要洗掉的檔案
string fileFullPath1 = vi.HLSPath + vi.HLSFileName + ".m3u8";//HLS流檔案
string fileFullPath2 = vi.HLSPath + vi.HLSFileName + "0.ts";//ts檔案
string fileFullPath3 = vi.HLSPath + vi.HLSFileName + "1.ts";//ts檔案
string fileFullPath4 = vi.HLSPath + vi.HLSFileName + "2.ts";//ts檔案
FileName = vi.HLSFileName;
// 判斷檔案路徑是否存在
if (File.Exists(fileFullPath1))
{
//洗掉檔案
File.Delete(fileFullPath1);
}
// 判斷檔案路徑是否存在
if (File.Exists(fileFullPath2))
{
//洗掉檔案
File.Delete(fileFullPath2);
}
// 判斷檔案路徑是否存在
if (File.Exists(fileFullPath3))
{
//洗掉檔案
File.Delete(fileFullPath3);
}
// 判斷檔案路徑是否存在
if (File.Exists(fileFullPath4))
{
//洗掉檔案
File.Delete(fileFullPath4);
}
}
#endregion
return FileName;
}
/// <summary>
/// 視頻資訊物體
/// </summary>
public class VideoInfo
{
/// <summary>
/// 用戶名
/// </summary>
public string username { get; set; }
/// <summary>
/// 密碼
/// </summary>
public string password { get; set; }
/// <summary>
/// IP
/// </summary>
public string ip { get; set; }
/// <summary>
/// 埠(默認554)
/// </summary>
public string port { get; set; }
/// <summary>
/// 轉換后HLS地址
/// </summary>
public string HLSPath { get; set; }
/// <summary>
/// 轉換后HLS檔案名
/// </summary>
public string HLSFileName { get; set; }
}
4.2.前端頁面
為了將轉換好的hls直播流可以顯示出來,我引入了Jquery、VideoJS及videojs-contrib-hlsJS插件(下載地址),插件均為引入頁面即可使用的,同時我還添加了判斷用戶離開頁面的方法,在用戶離開當前頁面時異步呼叫后臺代碼,將視瞥澩釋放,HTML完整代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta HTTP-EQUIV="pragma" CONTENT="no-cache">
<meta HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<meta HTTP-EQUIV="expires" CONTENT="0">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<meta content="email=no" name="format-detection" />
<meta content="telephone=no" name="format-detection" />
<script type="text/javascript" src="VideoJs/js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="VideoJs/js/video.min.js"></script>
<script type="text/javascript" src="VideoJs/js/videojs-contrib-hls.min.js"></script>
<link href="VideoJs/css/video-js.min.css" rel="stylesheet">
<title>demo</title>
</head>
<body>
<div>
<button id="btnPlay">播放</button>||
<a href="http://www.baidu.com" target="_self">測驗跳轉后清理視頻快取</a>
</div>
<div id="dvVideo">
<video id="my-video" style='margin-top:5px;' poster="b.gif" class="video-js vjs-big-play-centered" controls preload="auto" width="580" height="435" data-setup="{}"></video>
</div>
</body>
</html>
<script type="text/javascript">
//初始化VideoJS
$("#dvVideo").hide();
var videoObj = videojs('my-video');
var option = {};
var myPlayer;
myPlayer = videojs('my-video', option, function onPlayerReady() {
默認加載視頻
//var myPlayer = this;
//myPlayer.src({ src: "ffmpeg/1.m3u8", type: "application/x-mpegURL" });
//myPlayer.play();
});
myPlayer.controls = false;
</script>
<script>
$(function () {
//播放按鈕
$("#btnPlay").click(function () {
$("#dvVideo").show();
var param = new Object();
param.username="admin"; //攝像頭用戶名
param.password = "ty123456"; //密碼
param.ip = "192.168.16.35"; //IP地址
param.port = "554"; //埠號,默認554
param.HLSPath = "E:/HKVideoDemo/ffmpegToHLS/DataDemo/DataDemo/Demo/ffmpeg/"; //轉換后HLS地址,這里可以將專案中檔案夾的相對路徑轉為絕對路徑傳入
$.ajax({
url: 'DataForm.aspx?param=' + JSON.stringify(param)+'&type=add',
contentType: "application/json",
success: function (data) {
console.log(data);
//注意:必須要參考videojs-contrib-hls.min.js,只參考video.js無效
//這里src中的相對路徑根據實際專案設定
myPlayer.src({ src: "ffmpeg/" + data + ".m3u8", type: "application/x-mpegURL" });
myPlayer.play();
}
});
});
//離開頁面,釋放視頻,包括重繪、跳轉、關閉網頁、關閉瀏覽器等操作
$(window).bind('beforeunload',function () {
console.log("離開頁面,釋放視頻,");
$.ajax({
url: 'DataForm.aspx?type=stop',
dataType: "json",
success: function (data) {
}
});
});
});
</script>
5.原始碼
至此,前端和后端的開發就此完畢,由于只是一個簡單的DEMO事例,所以功能和用法都略顯粗糙,只是為了做一個簡單的記錄,將思路及方法表述出來,希望可以給以后的小伙伴提供一些思路,以及留待后用,
附原始碼下載地址:https://download.csdn.net/download/fwl562213140/12919777
6.轉載
碼字不易,轉載望留痕,
原文出處:https://blog.csdn.net/fwl562213140/article/details/109056188
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/175154.html
標籤:其他
