2016-09-21 7 views
0

각 프레임을 Raw ImageData 형식 (RGBA 순서로 픽셀 당 4 바이트)으로 보내서 WebSocket을 통해 비디오를 스트리밍하고 있습니다. 클라이언트에서 각 프레임을 받으면 (ArrayBuffer) putImageData을 사용하여이 이미지를 최대한 효율적으로 캔버스에 그립니다.캔버스에서 그리기 위해 ArrayBuffer를 ImageData로 변환합니다. 최적화

이 내 현재의 솔루션입니다 :

// buffer is an ArrayBuffer representing a properly-formatted image 
var array = new Uint8ClampedArray(buffer); 
var image = new ImageData(array, width, height); 
canvas.putImageData(image, 0, 0); 

그러나 오히려 느립니다. 내 이론과 같은 이유 :

  • 한 번 ImageData에, Uint8ClampedArray에 한 번, 세 번 복사되는, 그리고 마지막으로 캔버스에, 각 프레임 (30 번 당 (~ 크기 1메가바이트는) 배열 둘째).

  • 각 프레임에 대해 new을 두 번 사용하고 있는데 이는 가비지 수집기에 문제가 될 수 있습니다.

이러한 이론이 맞습니까? 그렇다면이 트릭을 최대한 빨리 만들 수있는 방법은 무엇입니까? 브라우저 관련 답변을 기꺼이 수락합니다.

답변

1

아니요, ImageData image과 TypedArray array은 정확히 동일한 버퍼 buffer을 공유합니다.

이들은 단지 포인터 일 뿐이므로 원래 버퍼는 절대로 "복사"되지 않습니다.

var ctx = document.createElement('canvas').getContext('2d'); 
 

 
var buffer = ctx.getImageData(0,0,ctx.canvas.width, ctx.canvas.height).data.buffer; 
 

 
var array = new Uint8ClampedArray(buffer); 
 

 
var image = new ImageData(array, ctx.canvas.width, ctx.canvas.height); 
 

 
console.log(array.buffer === buffer && image.data.buffer === buffer);
당신의 처리 시간이 문제에 대한

, 가장 좋은 방법은 단순히 videoElement에 직접 비디오 스트림을 전송하고 drawImage을 사용하는 것입니다.

+0

감사합니다. 예제가 많은 의미가 있습니다. 불행하게도 비디오 요소는 실시간으로 제공되어야하며 HTML5는 스트리밍을 기술적으로 지원하지 않기 때문에 – rvighne

+0

@rvighne 사실 그것은 스펙의 일부입니다. 'videoElement.captureStream()'메서드를 사용하여 videoElement에서 MediaStream을 가져올 수 있어야합니다.이 메서드는 현재 mozCaptureStream을 통해 FF로 시작됩니다. 그런 다음 WebRTC, socket.io 또는 WebSocket을 통해 보낼 수 있어야합니다. 마지막으로 클라이언트 쪽 videoElement의 'srcObject'를 전송 된 MediaStream으로 설정하면됩니다. 서버 측 지식은 없지만 녹화 된 파일을 비디오 스트림으로 변환하는 데 사용되는 프론트 사이드 데모는 다음과 같습니다. https://jsfiddle.net/usk05sfs/ – Kaiido

+0

스트림이 서버에서만 오는 경우 MediaSource API를 사용하고 파일의 청크를 보낼 수 있다고 생각합니다. https://developer.mozilla.org/en-US/docs/Web/API/MediaSource – Kaiido