media tutorial
1.0.0
createObjectURL
錯誤Failed to execute 'createObjectURL' on 'URL'
window . URL . createObjectURL ( data )
var binaryData = [ ] ;
binaryData . push ( data ) ;
window . URL . createObjectURL ( new Blob ( binaryData , { type : "application/zip" } ) ) ;
navigator.mediaDevices.getDisplayMedia
螢幕來源navigator.mediaDevices.getUserMedia
網路頭源 <!DOCTYPE html >
< html lang =" en " >
< head >
< meta charset =" UTF-8 " >
< meta name =" viewport " content =" width=device-width, initial-scale=1.0 " >
< meta http-equiv =" X-UA-Compatible " content =" ie=edge " >
< title > Document </ title >
</ head >
< body >
< style >
video {
width: 1000px;
height: 500px
}
</ style >
< video autoplay id =" video " > Video stream not available. </ video >
< script >
let video = document . getElementById ( 'video' ) ;
navigator . mediaDevices . getDisplayMedia ( {
video : true ,
audio : true
} )
. then ( stream => {
// we have a stream, attach it to a feedback video element
console . log ( stream ) ;
video . srcObject = stream ;
} , error => {
console . log ( "Unable to acquire screen capture" , error ) ;
} ) ;
</ script >
</ body >
</ html >
使用MediaRecorder
錄製影片或音訊的步驟
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {}
取得音訊視訊的stream
var mediaRecorder = new MediaRecorder(stream)
實例化mediaRecorder
, mediaRecorder
會不斷接受navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {}
所提供的stream
,並且它本身有多個方法mediaRecorder.start()
點選事件觸發開始錄製mediaRecorder.onstop = function(e) {}
往mediaRecorder
監聽停止事件var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });chunks = [];
這裡的chunks
會從無到有,隨著音訊串流被監聽,不斷增加,注意onstop
會觸發兩次,一開始未錄製和暫停都會觸發mediaRecorder.ondataavailable = function(e) {chunks.push(e.data);}
不斷監聽stream
,並往chunks
備份添加音視頻流的數據mediaRecorder.stop()
點選事件觸發暫停錄製var audioURL = URL.createObjectURL(blob);audio.src = audioURL;console.log("recorder stopped");
用blob
產生一個url
掛載到audio
或video
標籤上面去播放 var constraints = { audio : true } ;
var chunks = [ ] ;
navigator . mediaDevices . getUserMedia ( constraints )
. then ( function ( stream ) {
var mediaRecorder = new MediaRecorder ( stream ) ;
record . onclick = function ( ) {
mediaRecorder . start ( ) ;
console . log ( mediaRecorder . state ) ;
}
stop . onclick = function ( ) {
mediaRecorder . stop ( ) ;
console . log ( mediaRecorder . state ) ;
}
mediaRecorder . onstop = function ( e ) {
audio . setAttribute ( 'controls' , '' ) ;
audio . controls = true ;
var blob = new Blob ( chunks , { 'type' : 'audio/ogg; codecs=opus' } ) ;
chunks = [ ] ;
var audioURL = URL . createObjectURL ( blob ) ;
audio . src = audioURL ;
console . log ( "recorder stopped" ) ;
}
mediaRecorder . ondataavailable = function ( e ) {
chunks . push ( e . data ) ;
}
} )
. catch ( function ( err ) {
console . log ( 'The following error occurred: ' + err ) ;
} )
localPeerConnection = new RTCPeerConnection ( null ) ;
localPeerConnection . onicecandidate = function ( event ) {
if ( event . candidate ) {
remotePeerConnection . addIceCandidate ( new RTCIceCandidate ( event . candidate ) ) ; //answer方接收ICE
}
} ;
remotePeerConnection = new RTCPeerConnection ( null ) ;
remotePeerConnection . onicecandidate = function ( event ) {
if ( event . candidate ) {
localPeerConnection . addIceCandidate ( new RTCIceCandidate ( event . candidate ) ) ; //offer方接收ICE
}
} ;
remotePeerConnection . onaddstream = function gotRemoteStream ( event ) {
recordedVideo . srcObject = event . stream ;
} ;
localPeerConnection . addStream ( recordStream ) ;
localPeerConnection . createOffer ( function ( description ) { //description是offer方的 SD ==> 传输的内容
localPeerConnection . setLocalDescription ( description ) ;
remotePeerConnection . setRemoteDescription ( description ) ; //answer方接收offer的SD
remotePeerConnection . createAnswer ( function ( description ) {
remotePeerConnection . setLocalDescription ( description ) ; //answer方设置本身自己的SD
localPeerConnection . setRemoteDescription ( description ) ; //offer接收answer方的SD
} , function ( error ) {
console . log ( error )
} ) ; //answer方发送自己的SD
} , function ( error ) {
console . log ( error )
} ) ;
Blob
Binary Large Object
的縮寫,代表二進位類型的大物件
new Blob ( blobParts , [ options ] ) ;
blobParts: 叢集類型,叢集中的每一個連接起來構成Blob物件的數據,叢集中的每項元素可以是ArrayBuffer, ArrayBufferView, Blob, DOMString 。
options:可選項,字典格式類型,可指定以下兩個屬性:
var data1 = "a" ;
var data2 = "b" ;
var data3 = "<div style='color:red;'>This is a blob</div>" ;
var data4 = {
"name" : "abc"
} ;
var blob1 = new Blob ( [ data1 ] ) ;
var blob2 = new Blob ( [ data1 , data2 ] ) ;
var blob3 = new Blob ( [ data3 ] ) ;
var blob4 = new Blob ( [ JSON . stringify ( data4 ) ] ) ;
var blob5 = new Blob ( [ data4 ] ) ;
var blob6 = new Blob ( [ data3 , data4 ] ) ;
console . log ( blob1 ) ; //输出:Blob {size: 1, type: ""}
console . log ( blob2 ) ; //输出:Blob {size: 2, type: ""}
console . log ( blob3 ) ; //输出:Blob {size: 44, type: ""}
console . log ( blob4 ) ; //输出:Blob {size: 14, type: ""}
console . log ( blob5 ) ; //输出:Blob {size: 15, type: ""}
console . log ( blob6 ) ; //输出:Blob {size: 59, type: ""}
Blob
物件有一個slice
方法,傳回一個新的Blob
對象,包含了來源Blob
物件中指定範圍內的資料。
slice ( [ start ] , [ end ] , [ contentType ] )
Blob
裡的下標,表示第一個會被拷貝進新的Blob
的位元組起始位置。前開始計算。Blob
的一個下標,這個下標-1的位元組將被拷貝進新的Blob
的最後一個位元組。的消耗從後到前開始計算。type
Blob
一個新的文件類型。 var data = "abcdef" ;
var blob1 = new Blob ( [ data ] ) ;
var blob2 = blob1 . slice ( 0 , 3 ) ;
console . log ( blob1 ) ; //输出:Blob {size: 6, type: ""}
console . log ( blob2 ) ; //输出:Blob {size: 3, type: ""}
let href = URL . createObjectURL ( blob2 ) ; //浏览器可以直接打开href连接看输出
console . log ( href ) ; //abc
URL.createObjectURL URL
URL.createObjectURL()
靜態方法會建立一個DOMString
,其中包含一個表示參數中給出的URL
File
document
。對像或Blob
對象。
objectURL = URL . createObjectURL ( blob ) ;
URL.revokeObjectURL()
靜態方法用來釋放一個之前透過呼叫URL.createObjectURL()
建立URL
存在的URL
物件。文件的引用。
window . URL . revokeObjectURL ( objectURL ) ;
目前, Blob
物件主要運用在,處理大檔案分割上傳(利用Blob
中slice
方法),處理圖片canvas
跨域(避免增加crossOrigin = "Anonymous"
,產生目前網域的url
,然後URL.revokeObjectURL()
釋放, createjs
有用),以及隱藏視訊來源等等。
function upload ( blobOrFile ) {
var xhr = new XMLHttpRequest ( ) ;
xhr . open ( 'POST' , '/server' , true ) ;
xhr . onload = function ( e ) {
// ...
} ;
xhr . send ( blobOrFile ) ;
}
document . querySelector ( 'input[type="file"]' ) . addEventListener ( 'change' , function ( e ) {
var blob = this . files [ 0 ] ;
const BYTES_PER_CHUNK = 1024 * 1024 ; // 1MB chunk sizes.
const SIZE = blob . size ;
var start = 0 ;
var end = BYTES_PER_CHUNK ;
while ( start < SIZE ) {
upload ( blob . slice ( start , end ) ) ;
start = end ;
end = start + BYTES_PER_CHUNK ;
}
} , false ) ;
var xhr = new XMLHttpRequest ( ) ;
xhr . open ( 'GET' , '/path/to/image.png' , true ) ;
xhr . responseType = 'blob' ;
xhr . send ( )
xhr . onload = function ( e ) {
if ( this . status == 200 ) {
var blob = this . response ;
var img = document . createElement ( 'img' ) ;
var URL = window . URL || window . webkitURL ; //兼容处理
var objectUrl = URL . createObjectURL ( blob ) ;
img . onload = function ( e ) {
window . URL . revokeObjectURL ( img . src ) ; // 释放 url.
} ;
img . src = objectUrl ;
document . body . appendChild ( img ) ;
// ...
}
} ;
xhr . send ( ) ;
程式碼 | 作用 | 類型 |
---|---|---|
navigator.mediaDevices.getUserMedia(constraints).then(function(stream){}; | 根據音訊視訊來源產生stream | 媒體串流 |
mediaRecorder = new MediaRecorder(window.stream, options) | 依照音訊來源把stream 排序mediaRecorder 處理 | 媒體記錄器 |
mediaRecorder.ondataavailable = function (event) {recordedBlobs.push(event.data);} | 根據stream 取得每個片段的BlobEvent 並存入recordedBlobs 資料庫 | 斑點事件 |
let buffer = new Blob(recordedBlobs, {type: "video/webm"}); | 取得Blob 格式的音訊視訊串流 | 斑點 |
test.src = window.URL.createObjectURL(buffer); | 可用window.URL.createObjectURL 方法處理Blob並毆video 或audio 標籤播放 | 原始碼 |
recordStream = test.captureStream(); | 把Blob 轉化為MediaStream | 媒體串流 |
new RTCPeerConnection(null).addStream(recordStream); | 將recordStream 挖掘RTCPeerConnection 處理 | 媒體串流 |
mediaRecorder = new MediaRecorder ( window . stream , options ) ; // 设置音频录入源、格式
mediaRecorder . ondataavailable = function ( event ) {
// 这个会不断接受BlobEvent
console . log ( event ) ;
if ( event . data && event . data . size > 0 ) {
recordedBlobs . push ( event . data ) ;
}
} ; // 存放获取的数据
let buffer = new Blob ( recordedBlobs , {
type : "video/webm"
} ) ;
console . log ( buffer ) ;
test . src = window . URL . createObjectURL ( buffer ) ;
recordStream = test . captureStream ( ) ;
RTCP對等連接
媒體記錄器