HTML5 視訊直播(二)
提醒:本文最後更新於 1355 天前,文中所描述的資訊可能已發生改變,請謹慎使用。
上篇部落格中,我介紹了目前移動端唯一可行的 HTML5 直播方案:HLS。實際上,HLS 除了上回提到過的延遲很大這個缺點之外,在 iOS 的 Safari 瀏覽器中還只能全屏播放,也無法做到自動播放,這個是 iOS 系統對 Video 標籤統一做的限制。有沒有什麼辦法解決這些問題呢?
我們換個思路,既然原生 Video 有這樣那樣的問題,不如直接拋棄它。利用 Web Sockets 實現視訊流的實時傳輸,使用純 JS 進行視訊解碼,再用 Canvas 逐幀畫出影象,這不就實現了直播麼。當我有個這個想法之後,初步覺得可行,立馬開始一番搜尋,收穫頗豐。
本文要用到的 Web Sockets 在移動端支援度如下表:
瀏覽器 | 支援新標準的版本 |
---|---|
iOS Safari | 6.1+ |
Android Browser(Webview) | 4.4+ |
Chrome for Android | 42+ |
另外,轉換視訊格式、生成視訊流還需要用到一個神器:FFmpeg。
Mac 下最簡單的做法是通過 Homebrew 安裝,直接 brew install ffmpeg
就可以了。
Ubuntu 下可以先新增這個源:
sudo add-apt-repository ppa:mc3man/trusty-media
再 sudo apt-get install ffmpeg
Decoder in JavaScript
純 JS 實現的視訊解碼器我找到了兩個可用的:Broadway 和 jsmpeg。
是一個 H.264 解碼器,使用 Emscripten 工具從 Android 的 H.264 解碼器轉化而成,它還針對 WebGL 做了一些優化。
這個解碼器支援 mp4 字尾的視訊檔案,有一些限制:不支援 weighted prediction for P-frames 和 CABAC entropy encoding。例如 iPhone 拍攝的視訊它就不支援,可以用 FFmpeg 轉一下:
ffmpeg -i in.mp4 -vcodec libx264 -pass 1 -coder 0 -bf 0 -flags -loop -wpredp 0 out.mp4
下面是 H.264 解碼示例,視訊來自於我的 iPhone 拍攝。用閱讀器的同學請點到原文檢視。
這裡還有一個長一點的 Demo,點選檢視(載入完 6M 多的 mp4 檔案才開始播放,請耐心等待,流量黨慎入)。
則是一個 MPEG1 解碼器,它是由作者從零編寫出來的,並不像 Broadway 那樣是從其他語言翻譯而成,所以程式碼可讀性要好很多,程式碼也更輕量級。
jsmpeg 也對視訊檔案編碼方式有一些要求:不支援 B-Frames,視訊寬度必須是 2 的倍數。還是可以用 FFmpeg 來轉換:
ffmpeg -i in.mp4 -f mpeg1video -vf "crop=iw-mod(iw\,2):ih-mod(ih\,2)" -b 0 out.mpg
下面是 MPEG1 解碼示例,視訊來自於網上。用閱讀器的同學請點到原文檢視。
這裡也有一個長一點的 Demo,點選檢視(載入完 3M 多的 mpg 檔案才開始播放。其實沒什麼好看的,內容跟上面一樣,編碼格式不同而已)。
Live Streaming
看到這裡,大家肯定會說,這不是要一次性下完全部內容麼,怎能稱之為直播。是的,要實現直播,還要用 Web Sockets 實現一個實時傳輸流的服務。FFmpeg 支援很多直播流格式,但不支援 Web Sockets。解決方案是用 FFmpeg 開一個 HTTP 直播流,再開個 Node 服務轉一下。
詳細一點的過程是這樣的,用 NodeJS 監聽 FFmpeg 的 HTTP 直播地址,把收到的資料 通過 Web Sockets 廣播給所有客戶端。核心程式碼就是下面這幾行:
//HTTP Server to accept incomming MPEG Stream
var streamServer = require('http').createServer( function(request, response) {
request.on('data', function(data){
socketServer.broadcast(data, {binary:true});
});
}).listen(STREAM_PORT);
這段程式碼來自於上面介紹的 jsmpeg 專案,完整程式碼在這裡。啟動這個服務試試(需先裝好 ws 模組):
node ~/live/stream-server.js ququ 9091 9092
三個引數分別是服務標識、HTTP 埠、WS 埠。啟動後,螢幕上會顯示兩個地址:
Listening for MPEG Stream on http://127.0.0.1:9091/<secret>/<width>/<height>
Awaiting WebSocket connections on ws://127.0.0.1:9092/
好了,現在就可以使用 FFmpeg 來推送 HTTP 視訊流了:
ffmpeg -re -i fox.mpg -codec copy -f mpeg1video https://qgy18.com:9091/ququ/640/360
-re
引數表示以視訊實際播放速率解碼,不加這個引數一般會導致直播速率變得飛快。ququ
是啟動 Node 服務時指定的標識,可以做個簡單校驗,避免 Node 轉發不認識的流。最後的 640
和 360
是視訊的寬高,可以根據實際情況指定。
最後,稍微改一下前面的 Demo,讓 jsmpeg 從 WS 流中獲取資料就可以實現直播了:
var canvas = document.getElementById('videoCanvas');
var client = new WebSocket('ws://qgy18.qgy18.com:9092/');
var player = new jsmpeg(client, {canvas:canvas, autoplay: true});
Capture Webcam
上面演示的是從檔案中獲取視訊流進行直播,如果把資料來源換成攝像頭也很容易。FFmpeg 官方 wiki 上有在 Windows / MacOS / Linux 下讀取攝像頭的詳細指南。
以 Mac 為例,它支援 AVFoundation 和 QTKit 兩種不同的技術讀取攝像頭,在比較新的系統(10.7+)上,推薦使用 AVFoundation,QTKit 後續可能會被廢棄。
我的 Mac 系統是最新的,直接使用 AVFoundation。首先檢視可用攝像頭列表:
ffmpeg -f avfoundation -list_devices true -i ""
[AVFoundation input device @ 0x7fdd53c228c0] AVFoundation video devices:
[AVFoundation input device @ 0x7fdd53c228c0] [0] FaceTime HD Camera
[AVFoundation input device @ 0x7fdd53c228c0] [1] Capture screen 0
[AVFoundation input device @ 0x7fdd53c228c0] AVFoundation audio devices:
[AVFoundation input device @ 0x7fdd53c228c0] [0] Built-in Microphone
可以看到,編號為 0 的 video 裝置正是我想要的攝像頭(編號為 1 的裝置是電腦螢幕,直播螢幕也挺好玩),下面這行命令就可以捕捉它,並把視訊流推到之前的 Node 服務上:
ffmpeg -f avfoundation -framerate 30 -i "0" -f mpeg1video -b 500k -r 20 -vf scale=640:360 https://qgy18.com:9091/ququ/640/360
-b
和 -r
分別用來指定位元速率和幀率,可以根據實際情況調整。這樣,我攝像頭拍攝到的畫面,就被 FFMpeg 捕捉下來實時推給遠端 Node 服務,實時轉化成 WS 資料流,廣播給所有終端播放。雖然過程很曲折,但是基本上看不到延遲,體驗還是很不錯的。
最後,說幾個問題:
- 首先,最大的問題是:這種方案只實現了 Canvas 渲染畫面部分,無法支援聲音(沒聲音還好意思叫直播,摔!!!);
- 其次,JS 解碼能力還是稍微有點弱,最後的示例中我有意指定 scale 引數縮小了畫面,但在 iPhone 6 Plus 非自帶瀏覽器中還會卡(iOS 第三方 APP 趕緊放棄老系統,果斷的把 WKWebView 用起來吧~~~);
- 第三,好像略微有點蛋疼(好,這次就寫這麼多,收工。。。);
--EOF--
發表於 2015-04-25 14:33:24 ,並被新增「 HTML5 、 Video 」標籤 ,最後修改於 2015-04-26 22:00:49 。檢視本文 Markdown 版本 »
提醒:本文最後更新於 1355 天前,文中所描述的資訊可能已發生改變,請謹慎使用。
相關推薦
HTML5 視訊直播(二)
提醒:本文最後更新於 1355 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 上篇部落格中,我介紹了目前移動端唯一可行的 HTML5 直播方案:HLS。實際上,HLS 除了上回提到過的延遲很大這個缺點之外,在 iOS 的 Safari 瀏覽器中還只能全屏播放,也無法做到自動播放,這個是 i
HTML5 視訊直播(三)
提醒:本文最後更新於 1349 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 連續寫了兩篇有關視訊直播的文章之後,有同學問我為什麼沒有 WebRTC 相關內容。實際上一開始我就說過,我的需求是在移動 WEB 端上直播視訊,而移動端瀏覽器現階段對「WebRTC 的支援度」非常不樂觀,所以我就
HTML5 視訊直播(一)
提醒:本文最後更新於 776 天前,文中所描述的資訊可能已發生改變,請謹慎使用。 前不久工作中遇到了在移動 WEB 端直播視訊的需求,研究了一下相關技術,記錄一下。 目前 WEB 上主流的視訊直播方案有 HLS 和 RTMP,移動 WEB 端目前就只有 HLS 能用,我們重點介紹它。 upda
HTML5學習筆記(二)視訊與音訊處理
一、<video> 1、<video>是H5的新標籤,用來處理視訊,在此之前,各網站用來處理視訊一直使用flash技術 flash的缺點有以下幾方面,首先原生瀏覽器原生不支援,需要外掛,其次過多的使用會導致網站效能變差,最後就是
web前端基礎教學視訊分享(二)html5+css3基礎教學
與卿再世相逢日,玉樹臨風一少年 夜未深,夢未成,怎敢睡去。 【寫在前面】 前端一入深似海,從此黑絲漸發白。 孤燈下,執一本。 程式設計不易,且行且放棄? 【分享與你】(百度雲盤永久有效) 連結:https://pan.baidu.com/s/1gr66gQawvgRSKjQQoO4GDQ
iOS直播(二)GPUImage音視訊採集
GPUImage是一個開源的基於GPU的第三方影象處理庫,可以對影象進行美化、新增各種濾鏡等。GPUImage的視訊採集部分的原始碼,也是和上文中的AVFoundation實現採集(https://blog.csdn.net/dolacmeng/article/
HTML5基礎小結(二)——標簽小例
加速 支持 ide oat enter controls 畫圓 side tint 隨篇博客的思維導圖。繼續: 二。看下標簽的使用,這裏看幾個小樣例(效果圖不再給出): 1。結構標簽的使用,這裏來看一個頁面的布局:<!doc
HTML5的學習(二)HTML5標籤
3.按功能排列標籤 (注:紅色為HTML5不支援的,藍色為HTML5新增的標籤元素。) 3.1基本 標籤 描述 HTML4 HTML5 <!--...--> 定義註釋。
資料庫視訊總結(二)——增刪改查
查: 簡單的SELECT語句: 例如: select student_Name,student_Sex from student_Info 1、可以當做計算機來使用: select 12*13 as 計算結果 2、讓列名發生變化: Select 原來的列名 as 新的列
即時通訊音視訊開發(二):視訊編解碼之數字視訊介紹
前言 即時通訊應用中的實時音視訊技術,幾乎是IM開發中的最後一道高牆。原因在於:實時音視訊技術 = 音視訊處理技術 + 網路傳輸技術 的橫向技術應用集合體,而公共網際網路不是為了實時通訊設計的。 系列文章 本文是系列文章中的第2篇,本系列文章的大綱如下: 《即時
數字視訊基礎(二)
轉自https://blog.csdn.net/shanghaiqianlun/article/details/26484771 2. 常用數字視訊標準 2.1 BT656
零基礎實現攝像頭的全平臺直播 (二)公網直播的實現
接上回,我們實現內網直播,可以實現直播的web觀看,該篇博文我們將實現公網的直播。 由於通用最多都是 window系統,我們的軟體也是可以在Windows上執行,我們後面就以window為例進行操作 下載穿透軟體 下載地址:https://natapp.cn/#do
golang 流量統計系統視訊總結(二)
總體流程 解析使用者訪問行為日誌部分 程式碼實現: package main import ( "bufio" "crypto/md5" "encoding/hex" "flag" "github.com/mediocregopher/radix.v2/p
HTML5 基礎知識(二)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title></title> </head
[持續更新]HTML5學習筆記(二)
1. 元素分類 元資料元素(metadata element):由此可見主要是<meta>元素中的事情了,向瀏覽器提供資訊和指示; 流元素(flow element):聽名字怪異,但是其實是規定這些元素可以成為父元素; 短語元素(phrasing elemen
Native和html5的互動(二)Android native傳資料給js
js裡面 某函式用來接收android傳過來的資料 function onDeviceScanResult(data) { alert("Device Scan Result:" + data); } Android裡面把資料拼接成字串發給js ta); }W
iOS音視訊專欄(二)WebRTC音訊模組在iOS上的應用
公司的專案是通過WebRTC的APM(Audio Processing Module)模組進行的聲音處理(降噪,增益,回聲消除等),通過呼叫audio_device獲取裝置音訊硬體。整套音訊處理都是
Intel智慧工業相機功能視訊演示(二)
更多精彩內容,請微信搜尋“FPGAer俱樂部”關注我們。 Intel推出工業智慧相機方案 APOLLO ISLAND,該相機硬體系統如下圖所示,CPU採用Intel ATOM x5 E3930,FPGA採用CycloneV GT 5CGTFD7D5F27C7N, Senso
從Android原生角度看移動html5開發APP(二)之整體mui初始化
有幾天沒有寫用html5開發移動app的總結了,今天抽出點時間來總結一下吧。 不多說直接入主題: 1、html就是一個框架,雖然說有點想layout,但是還是有點不一樣的,具體的就是一個是標籤,一個是具體控制元件。在移動開發中html用的最多的就是塊標籤即<div&g
Android實現錄屏直播(二)需求才是硬道理之產品功能調研
前面的Android實現錄屏直播(一)ScreenRecorder的簡單分析一文中我們對 ScreenRecorder 這個開源 Demo 中的實現機制大概有了瞭解,但在繼續寫這個系列文章的時候發現每一個細節都太緊密了,稍微不注意就會深入每個知識