2

我想使用MediaStream.captureStream()方法,但是由于规范和错误,它要么变得无用,要么我完全错误地使用它。
我知道captureStream最大帧速率作为参数,而不是恒定的,它甚至不能保证,但是可以更改 MediaStream currentTime(目前在 Chrome 中,在 Firefox 中它没有效果,但作为回报有 requestFrame,在 Chrome 中不可用),但手动框架请求或设置框架位置的想法MediaStream应该覆盖此效果。它没有。

在 Firefox 中,它逐帧平滑地渲染视频,但视频结果与用于处理的挂钟时间一样长。
在 Chrome 中,有一些可疑的黑框或重新排序的框(目前我不关心它,直到 FPS 匹配),手动设置currentTime没有给出任何结果,与 FF 中的结果相同。

我使用来自MediaStream Capture Canvas 和 Audio 同时回答的修改后的代码。

const FPS = 30;
var cStream, vid, recorder, chunks = [], go = true,
	Q = 61, rec = document.getElementById('rec'),
	canvas = document.getElementById('canvas'),
	ctx = canvas.getContext('2d');
	ctx.strokeStyle = 'rgb(255, 0, 0)';

function clickHandler() {
	this.textContent = 'stop recording';
	//it has no effect no matter if it is empty or set to 30
	cStream = canvas.captureStream(FPS);
	recorder = new MediaRecorder(cStream);
	recorder.ondataavailable = saveChunks;
	recorder.onstop = exportStream;
	this.onclick = stopRecording;
	recorder.start();
	draw();
}

function exportStream(e) {
	if (chunks.length) {
		var blob = new Blob(chunks)
		var vidURL = URL.createObjectURL(blob);
		var vid2 = document.createElement('video');
		vid2.controls = true;
		vid2.src = vidURL;
		vid2.onend = function() {
			URL.revokeObjectURL(vidURL);
		}
		document.body.insertBefore(vid2, vid);
	} else {
		document.body.insertBefore(document.createTextNode('no data saved'), canvas);
	}
}

function saveChunks(e) {
  e.data.size && chunks.push(e.data);
}

function stopRecording() {
	go = false;
	this.parentNode.removeChild(this);
	recorder.stop();
}

var loadVideo = function() {
	vid = document.createElement('video');
	document.body.insertBefore(vid, canvas);
	vid.oncanplay = function() {
		rec.onclick = clickHandler;
		rec.disabled = false;
		canvas.width = vid.videoWidth;
		canvas.height = vid.videoHeight;
		vid.oncanplay = null;
		ctx.drawImage(vid, 0, 0);
	}

	vid.onseeked = function() {
		ctx.drawImage(vid, 0, 0);
      /*
      Here I want to include additional drawing per each frame,
      for sure taking more than 180ms
      */
		if(cStream && cStream.requestFrame) cStream.requestFrame();
		draw();
	}

	vid.crossOrigin = 'anonymous';
	vid.src = 'https://dl.dropboxusercontent.com/s/bch2j17v6ny4ako/movie720p.mp4';
	vid.currentTime = 0;
}

function draw() {
	if(go && cStream) {
		++Q;
		cStream.currentTime = Q / FPS;
		vid.currentTime = Q / FPS;
	}
};

loadVideo();
<button id="rec" disabled>record</button><br>
<canvas id="canvas" width="500" height="500"></canvas>

有没有办法让它运行?
目标是加载视频,处理每一帧(在我的情况下这很耗时)并返回处理后的帧。

脚注:我不想使用 ffmpeg.js、外部服务器或其他技术。我可以通过经典的 ffmpeg 处理它,根本不使用 JavaScript,但这不是这个问题的重点,更多的是关于 MediaStream 的可用性/成熟度。这里的上下文是 Firefox/Chrome,但也可能是 node.js 或 nw.js。如果这完全可行或正在等待错误修复,那么下一个问题将是为其提供音频,但我认为这将是一个单独的问题。

4

0 回答 0