如何正确录制画布视频,以便所有视频播放器都支持输出视频



我正在使用Media Recorder API录制一个html画布,然后将视频上传到服务器,之后我想使用web共享API 将该视频共享到WhatsApp等其他应用

我可以录制Canvas并上传到服务器,但视频的持续时间很短,当我将视频分享到WhatsApp时,什么分享视频是失真的

这是我录制画布的代码

recordBtn.addEventListener("click", () => {
recording = !recording;
if(recording){
recordBtn.textContent = "Stop";
const stream = can.captureStream(25);
mediaRecorder = new MediaRecorder(stream, {
mimeType: 'video/webm;codecs=vp9',
ignoreMutedMedia: true
});
recordedChunks = [];
mediaRecorder.ondataavailable = e => {
if(e.data.size > 0){
e.target.videoBitsPerSecond=10
console.log(e)
recordedChunks.push(e.data);
}
};
var currentDateTime = new Date();
startTime=currentDateTime.getTime() / 1000;
mediaRecorder.start();
} else {
recordBtn.textContent = "Record"
mediaRecorder.stop();

setTimeout(() => {
const blob = new Blob(recordedChunks, {
type: "video/webm",
audioBitsPerSecond: 100000,
videoBitsPerSecond: 4000000
});
var currentDateTime = new Date();
endTime=currentDateTime.getTime() / 1000;
var duration=endTime-startTime
console.log(duration)
ysFixWebmDuration(blob, duration, function(fixedBlob) {

var data = new FormData();
data.append('file', fixedBlob);
console.log(data)
$.ajax({
type: 'POST',
data:data,
contentType: false,
processData: false,
url:`http://hthbeats.pythonanywhere.com/file` 
}).then(function( data, textStatus, jqXHR ) {
data=data

})
});


},0);
}
});

这是将媒体共享到其他应用程序的代码

async function m(){

let blob = await fetch("https://hthbeats.pythonanywhere.com/static/t.webm").then(r => r.blob());
console.log(blob)
var file = new File([blob], "t.webm", {type: 'video/webm'});
const filesArray = [file];
console.log(filesArray)

const shareData = {
files:filesArray,
title: 'HTh-Beats',
text: 'Video sharing ',
url: "https://hthbeats.pythonanywhere.com/static/t.webm"
}
await navigator.share(shareData)
}


让它运行20秒,然后您将获得MP4格式的录制视频的URL。

function Recorder(canvas, fps) {
var fps = fps || 30;
var ctx = canvas.getContext("2d");
var videoStream = canvas.captureStream(fps);
var mediaRecorder = new MediaRecorder(videoStream);
var videoURL;
var chunks = [];
mediaRecorder.ondataavailable = function(e) {
chunks.push(e.data);
}
function download(dataurl, filename) {
const link = document.createElement("a");
link.href = dataurl;
link.download = filename;
link.click();
}
mediaRecorder.onstop = function(e) {
var blob = new Blob(chunks, {
'type': 'video/mp4'
});
chunks = [];
videoURL = URL.createObjectURL(blob);
//console.log("mp4 video url:", videoURL);
var myReader = new FileReader();
myReader.readAsDataURL(blob);
myReader.addEventListener("loadend", function(e) {
document.getElementById('video').src = e.srcElement.result;
document.getElementById('canvas').hidden = true;
document.getElementById('video').hidden = false;
});
}
mediaRecorder.ondataavailable = function(e) {
chunks.push(e.data);
}
this.start = () => mediaRecorder.start();
this.stop = () => mediaRecorder.stop();
this.pause = () => mediaRecorder.pause();
this.resume = () => mediaRecorder.resume();
this.getUrl = () => videoURL;
this.download = (fileName) => {
if (videoURL != "")
download(videoURL, fileName)
}
}

/**
* requestAnimationFrame
*/
window.requestAnimationFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
})();

// Configs
var Configs = {
backgroundColor: '#eee9e9',
particleNum: 1000,
step: 5,
base: 1000,
zInc: 0.001
};

// Vars
var canvas,
context,
screenWidth,
screenHeight,
centerX,
centerY,
particles = [],
hueBase = 0,
simplexNoise,
zoff = 0,
gui;

// Initialize
function init() {
canvas = document.getElementById('canvas');
window.addEventListener('resize', onWindowResize, false);
onWindowResize(null);
for (var i = 0, len = Configs.particleNum; i < len; i++) {
initParticle((particles[i] = new Particle()));
}
simplexNoise = new SimplexNoise();
canvas.addEventListener('click', onCanvasClick, false);

rec = new Recorder(canvas);
setTimeout(rec.start, 100);
setTimeout(rec.stop, 20000);
update();
}

// Event listeners
function onWindowResize(e) {
screenWidth = canvas.width = window.innerWidth;
screenHeight = canvas.height = window.innerHeight;
centerX = screenWidth / 2;
centerY = screenHeight / 2;
context = canvas.getContext('2d');
context.lineWidth = 0.3;
context.lineCap = context.lineJoin = 'round';
}
function onCanvasClick(e) {
context.save();
context.globalAlpha = 0.8;
context.fillStyle = Configs.backgroundColor;
context.fillRect(0, 0, screenWidth, screenHeight);
context.restore();
simplexNoise = new SimplexNoise();
}

// Functions
function getNoise(x, y, z) {
var octaves = 4,
fallout = 0.5,
amp = 1,
f = 1,
sum = 0,
i;
for (i = 0; i < octaves; ++i) {
amp *= fallout;
sum += amp * (simplexNoise.noise3D(x * f, y * f, z * f) + 1) * 0.5;
f *= 2;
}
return sum;
}
function initParticle(p) {
p.x = p.pastX = screenWidth * Math.random();
p.y = p.pastY = screenHeight * Math.random();
p.color.h = hueBase + Math.atan2(centerY - p.y, centerX - p.x) * 180 / Math.PI;
p.color.s = 1;
p.color.l = 0.5;
p.color.a = 0;
}

// Update
function update() {
var step = Configs.step,
base = Configs.base,
i, p, angle;
for (i = 0, len = particles.length; i < len; i++) {
p = particles[i];
p.pastX = p.x;
p.pastY = p.y;
angle = Math.PI * 6 * getNoise(p.x / base * 1.75, p.y / base * 1.75, zoff);
p.x += Math.cos(angle) * step;
p.y += Math.sin(angle) * step;
if (p.color.a < 1) p.color.a += 0.003;
context.beginPath();
context.strokeStyle = p.color.toString();
context.moveTo(p.pastX, p.pastY);
context.lineTo(p.x, p.y);
context.stroke();
if (p.x < 0 || p.x > screenWidth || p.y < 0 || p.y > screenHeight) {
initParticle(p);
}
}
hueBase += 0.1;
zoff += Configs.zInc;
requestAnimationFrame(update);
}

/**
* HSLA
*/
function HSLA(h, s, l, a) {
this.h = h || 0;
this.s = s || 0;
this.l = l || 0;
this.a = a || 0;
}
HSLA.prototype.toString = function() {
return 'hsla(' + this.h + ',' + (this.s * 100) + '%,' + (this.l * 100) + '%,' + this.a + ')';
}
/**
* Particle
*/
function Particle(x, y, color) {
this.x = x || 0;
this.y = y || 0;
this.color = color || new HSLA();
this.pastX = this.x;
this.pastY = this.y;
}

// Run
init();
body {
font-family: sans-serif;
padding: 0;
margin: 0;
background-color: #eee9e9;
overflow: hidden;
}
canvas {
position: absolute;
top: 0;
left: 0;
}
<center><video autoplay hidden=true id='video' width="320" height="240" controls></center>
</video>
<canvas id='canvas'></canvas>
<script src="https://rawgit.com/akm2/simplex-noise.js/master/simplex-noise.js"></script>

rec = new Recorder(yourcanvaselement,FPS); /// fps is optional and defaults to 30.
then:
rec.start()
rec.pause()
rec.resume()
rec.stop()
rec.download("filename.mp4") /// or any name.mp4
to get the recording URL without downloading:
rec.getUrl()

最新更新