一匿又、合并腳本
最終使用的jsmpeg.min.js其實(shí)就是源碼src目錄下的所有js合并而成程拭。可以自行修改筷狼,然后使用以下腳本合并運(yùn)行瓶籽。前幾個系列已經(jīng)學(xué)習(xí)了視頻解碼部分,音頻部分使用了mp2+webaudio埂材,暫時不作分析∷芩常現(xiàn)在再把剩余的幾個類簡單看一下。
var gulp = require('gulp');
var concat = require("gulp-concat");
var uglify = require('gulp-uglify');
gulp.task('concat', function() {
gulp.src(['src/jsmpeg.js',
'src/video-element.js',
'src/player.js',
'src/buffer.js',
'src/ajax.js',
'src/ajax-progressive.js',
'src/websocket.js',
'src/ts.js',
'src/decoder.js',
'src/mpeg1.js',
'src/mp2.js',
'src/webgl.js',
'src/canvas2d.js',
'src/webaudio.js'
])
.pipe(concat('jsmpeg.min3.js'))
//.pipe(uglify())
.pipe(gulp.dest(''));
});
gulp.task('default', ['concat']);
二俏险、jsmpeg.js
這里封裝了命名空間及子空間严拒,入口指向了JSMpeg.CreateVideoElements
CreateVideoElements: function() {
var elements = document.querySelectorAll('.jsmpeg');
for (var i = 0; i < elements.length; i++) {
new JSMpeg.VideoElement(elements[i]);
}
}
三、video-element.js
// A Video Element wraps the Player, shows HTML controls to start/pause
// the video and handles Audio unlocking on iOS. VideoElements can be
// created directly in HTML using the <div class="jsmpeg"/> tag.
最終指向了這里
// Create the player instance
this.player = new JSMpeg.Player(url, options);
element.playerInstance = this.player;
四竖独、readme里的參數(shù)說明
The url
argument accepts a URL to an MPEG .ts file or a WebSocket server (ws://...).
The options
argument supports the following properties:
-
canvas
– the HTML Canvas elment to use for video rendering. If none is given, the renderer will create its own Canvas element. -
loop
– whether to loop the video (static files only). Defaulttrue
. -
autoplay
- whether to start playing immediately (static files only). Defaultfalse
. -
audio
- whether to decode audio. Defaulttrue
. -
video
- whether to decode video. Defaulttrue
. -
poster
– URL to an image to use as the poster to show before the video plays. -
pauseWhenHidden
– whether to pause playback when the tab is inactive. Defaulttrue
. Note that browsers usually throttle JS in inactive tabs anyway. -
disableGl
- whether to disable WebGL and always use the Canvas2D renderer. Defaultfalse
. -
preserveDrawingBuffer
– whether the WebGL context is created withpreserveDrawingBuffer
- necessary for "screenshots" viacanvas.toDataURL()
. Defaultfalse
. -
progressive
- whether to load data in chunks (static files only). When enabled, playback can begin before the whole source has been completely loaded. Defaulttrue
.邊下邊播 -
throttled
- when usingprogressive
, whether to defer loading chunks when they're not needed for playback yet. Defaulttrue
. -
chunkSize
- when usingprogressive
, the chunk size in bytes to load at a time. Default1024*1024
(1mb). -
decodeFirstFrame
- whether to decode and display the first frame of the video. Useful to set up the Canvas size and use the frame as the "poster" image. This has no effect when usingautoplay
or streaming sources. Defaulttrue
. -
maxAudioLag
– when streaming, the maximum enqueued audio length in seconds. -
videoBufferSize
– when streaming, size in bytes for the video decode buffer. Default 512*1024 (512kb). You may have to increase this for very high bitrates. -
audioBufferSize
– when streaming, size in bytes for the audio decode buffer. Default 128*1024 (128kb). You may have to increase this for very high bitrates.
All options except from canvas
can also be used with the HTML Element through data-
attributes. E.g. to specify looping and autoplay in JavaScript:
var player = new JSMpeg.Player('video.ts' {loop: true, autoplay: true});
or HTML
<div class="jsmpeg" data-url="video.ts"
data-loop="true" data-autoplay="true"></div>
Note that camelCased options have to be hyphenated when used as data attributes. E.g. decodeFirstFrame: true becomes data-decode-first-frame="true" for the HTML element.
五裤唠、搭建測試環(huán)境
1.README.md
JSMpeg is a Video Player written in JavaScript. It consists of an MPEG-TS demuxer, MPEG1 video & MP2 audio decoders, WebGL & Canvas2D renderers and WebAudio sound output. JSMpeg can load static videos via Ajax and allows low latency streaming (~50ms) via WebSockets.
JSMpeg can decode 720p Video at 30fps on an iPhone 5S, works in any modern browser (Chrome, Firefox, Safari, Edge) and comes in at just 20kb gzipped.
Using it can be as simple as this:
<script src="jsmpeg.min.js"></script>
<div class="jsmpeg" data-url="video.ts"></div>
Some more info and demos: jsmpeg.com
2.jsmpeg.com的例子
查看html的element,然后下載這個示例的Ts文件
<div class="jsmpeg full-width" data-url="bjork-all-is-full-of-love.ts" style="..."</div>
發(fā)現(xiàn)本地直接打開這個html是播放不了的莹痢,需要部署到服務(wù)器上巧骚。這下可以播放本地文件了,可以參照readme加上data-loop="true" data-autoplay="true"
這些控制屬性格二。
這里把div換成canvas劈彪,或者把TS本地文件變成mpg文件,都播放不了顶猜。
3.使用script代碼來播放
<body>
<canvas id="video-canvas"></canvas>
<script type="text/javascript" src="jsmpeg.min.js"></script>
<script type="text/javascript">
var canvas = document.getElementById('video-canvas');
var player = new JSMpeg.Player('bjork-all-is-full-of-love.ts',
{canvas:canvas,loop: true, autoplay: true});
</script>
</body>
options參數(shù)參見readme.md
4.不支持 B-Frames沧奴,視頻寬度必須是 2 的倍數(shù)
JSMpeg only supports playback of MPEG-TS containers with the MPEG1 Video Codec and the MP2 Audio Codec. The Video Decoder does not handle B-Frames correctly (though no modern encoder seems to use these by default anyway) and the width of the video has to be a multiple of 2.
You can encode a suitable video using ffmpeg like this:
ffmpeg -i in.mp4 -f mpegts -codec:v mpeg1video -codec:a mp2 -b 0 out.ts
5.使用websocket(nginx)
這里我先嘗試用nginx搭建websocket,參考配置 Nginx 反向代理 WebSocket长窄,先用node.js的ws模塊啟動了ws://localhost:8010
滔吠,可以連接成功。但是挠日,后面使用niinx配置反向代理失敗了疮绷,連接ws://ws.repo/
一直失敗,原因不明嚣潜,配置文件如下:
worker_processes 1;
error_log logs/error.log debug;
events {
worker_connections 1024;
}
http{
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream ws_server {
#ip_hash;
server localhost:8010;
}
# 以下配置是在server上下文中添加冬骚,location指用于websocket連接的path。
server {
listen 80;
server_name ws.repo;
access_log /var/log/nginx/yourdomain.log;
location / {
proxy_pass http://192.168.198.102:8010;
#proxy_pass http://ws_server/;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
6.參考jsmpeg官方文檔(這里,官網(wǎng)也在使用node.js來操作websocket-relay.js)
這里先npm init ws -D
只冻,然后node websocket-relay ququ 9091 9092
Listening for incomming MPEG-TS Stream on http://127.0.0.1:9091/<secret>
Awaiting WebSocket connections on ws://127.0.0.1:9092/
注意看庇麦,推流要推到上面那個9091端口;而播放視頻則要用下面那個WS的9092端口∠驳拢現(xiàn)在我們拿在線測試websocket工具已經(jīng)可以連接9092了
然后就是推流操作山橄,這里參考HTML5 視頻直播(二)是看不到的,原因就是那個-f mpeg1video:
ffmpeg -re -i bjork-all-is-full-of-love.ts -codec copy
-f mpeg1video http://127.0.0.1:9091/ququ
需要把-f mpeg1video改成-f mpegts舍悯,因?yàn)槲覀冇玫氖莟s后綴的文件啊航棱。這也是參照官網(wǎng)readme才發(fā)現(xiàn)的,另外就是demo傳的url就是ws的字符串萌衬。
<body>
<canvas id="video-canvas"></canvas>
<script type="text/javascript" src="jsmpeg.min.js"></script>
<script type="text/javascript">
var canvas = document.getElementById('video-canvas');
//var client = new WebSocket('ws://127.0.0.1:9092');
//var player = new JSMpeg.Player(client,
//{canvas:canvas,loop: true, autoplay: true});
var player = new JSMpeg.Player('ws://127.0.0.1:9092/',
{canvas:canvas,loop: true, autoplay: true});
</script>
</body>
六饮醇、其它
1.ffmpeg是有聲音的,雖然 HTML5 視頻直播(二)的作者寫著沒有聲音奄薇。估計(jì)是代碼庫版本有變化驳阎。另外 mpg格式也不支持,現(xiàn)在是TS格式馁蒂。參考[總結(jié)]視音頻編解碼技術(shù)零基礎(chǔ)學(xué)習(xí)方法
還有視音頻編解碼學(xué)習(xí)工程:TS封裝格式分析器
2.對比Broadway呵晚,ffmpeg是從零寫出的,可讀性好很多沫屡。
Broadway 是一個 H.264 解碼器饵隙,使用 Emscripten 工具從 Android 的 H.264 解碼器轉(zhuǎn)化而成,它還針對 WebGL 做了一些優(yōu)化沮脖。
這個解碼器支持 mp4 后綴的視頻文件金矛,有一些限制:不支持 weighted prediction for P-frames 和 CABAC entropy encoding。例如 iPhone 拍攝的視頻它就不支持勺届,可以用 FFmpeg 轉(zhuǎn)一下:
ffmpeg -i in.mp4 -vcodec libx264 -pass 1 -coder 0 -bf 0 -flags -loop -wpredp 0 out.mp4
下面是 H.264 解碼示例驶俊,視頻來自于我的 iPhone 拍攝。用閱讀器的同學(xué)請點(diǎn)到原文查看免姿。
這里還有一個長一點(diǎn)的 Demo饼酿,點(diǎn)擊查看(加載完 6M 多的 mp4 文件才開始播放,請耐心等待胚膊,流量黨慎入)故俐。
3.HTML5直播技術(shù)探究
傳統(tǒng)直播技術(shù),大多使用RTMP通過Flash進(jìn)行傳輸紊婉。隨著HTML5的逐漸實(shí)現(xiàn)药版,<video>等媒體標(biāo)簽的瀏覽器支持, 很多視頻逐漸向Html5靠攏喻犁。Youtube等視頻網(wǎng)站紛紛開始使用HTML5播放器槽片,然而縱觀當(dāng)前的直播網(wǎng)站何缓,大多還是依賴Flash。直播為何不采用HTML5呢筐乳?
目前的HTML5直播思路有以下幾種歌殃。
一是使用js調(diào)用WebGL渲染視頻乔妈,用websocket/XHR傳輸蝙云,比如jsmpeg項(xiàng)目, 實(shí)現(xiàn)了一個MPEG1的js解析器路召,該項(xiàng)目存在很多bug(今天凌晨剛剛收到j(luò)smpeg作者的github信息勃刨,說他已經(jīng)修復(fù)了好幾個我提過的bug,并且重寫了代碼)股淡,另外由于MPEG1的效能極低(比GIF好不了多少)身隐,傳輸?shù)囊曨l 質(zhì)量較差,而且js解析消耗很高CPU唯灵,這種方案不是很理想贾铝。
二是使用Native的解碼方案,使用MediaSourceExtension埠帕。比如B站開源的flv.js
4.我想在egret里面 引入第三方j(luò)smpg庫
這里有回復(fù)提供了jsmpeg的d.ts文件