-
Notifications
You must be signed in to change notification settings - Fork 19
/
videocanvas.html
176 lines (161 loc) · 6.2 KB
/
videocanvas.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>MediaRecorder使用示例</title>
</head>
<style>
canvas {
box-shadow: 0 0 10px gray;
display: block;
}
</style>
<h3 style="text-align: center;margin-top:10px;">MediaRecorder使用示例</h3>
<p style="text-align: center;margin-top:10px;color:grey">点击画布在视频上作画<button id="clearBtn">清除笔迹</button></p>
<div style="text-align: center;margin-top:10px;">
<canvas id="canvas" height=360 width=640 style="width:640px;margin:auto;"></canvas>
<video src="./video.mp4" id="srcvideo" autoplay=true style="display:none;"></video>
</div>
<div style="text-align: center;margin-top:10px;">
<button id="startBtn" disabled>开始录制</button>
<button id="pauseBtn" disabled>暂停录制</button>
<button id="resumeBtn" disabled>恢复录制</button>
<button id="stopBtn" disabled>结束录制</button>
</div>
<div style="text-align: center;margin-top:20px;">
<p>切换录制编码格式</p>
<p><input type="radio" name="format" value="video/webm;codecs=vp8" onclick="setFormatSelect('video/webm;codecs=vp8')">video/webm;codecs=vp8</p>
<p><input type="radio" name="format" value="video/webm;codecs=vp9" onclick="setFormatSelect('video/webm;codecs=vp9')" checked="checked">video/webm;codecs=vp9</p>
<p><input type="radio" name="format" value="video/webm;codecs=h264" onclick="setFormatSelect('video/webm;codecs=h264')">video/webm;codecs=h264</p>
<p><input type="radio" name="format" value="video/webm;codecs=avc1" onclick="setFormatSelect('video/webm;codecs=avc1')">video/webm;codecs=avc1</p>
<p><input type="radio" name="format" value="video/x-matroska;codecs=avc1" onclick="setFormatSelect('video/x-matroska;codecs=avc1')">video/x-matroska;codecs=avc1</p>
</div>
<div style="text-align: center;margin-top:20px;">
<p><input type="checkbox" name="showconsole" onclick="setShowConsole(this)">是否在控制台显示ondataavailable</p>
</div>
<div style="margin-top:50px;text-align: center;font-size:14px;">view source: <a href="https://github.com/wendychengc/media-recorder-video-canvas/tree/master" target="_blank">https://github.com/wendychengc/media-recorder-video-canvas/tree/master</a></div>
<script>
var allChunks = [];
var mousex = 0;
var mousey = 0;
var drawArray = [];
var showDataAvailable = false;
init();
function init() {
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
var srcvideo = document.getElementById("srcvideo")
document.body.onmousedown = e => {
srcvideo.play()
playCanvas(srcvideo, ctx)
}
clearBtn.onclick = e => {drawArray=[]}
canvas.onmousemove = e => {
const {
top,
left
} = canvas.getBoundingClientRect();
mousex = e.clientX - left;
mousey = e.clientY - top;
};
canvas.onmousedown = e => {
const {
top,
left
} = canvas.getBoundingClientRect();
var downx = e.clientX - left;
var downy = e.clientY - top;
drawArray.push({
x: downx,
y: downy
})
};
setRecorder();
setFormatSelect('video/webm;codecs=vp9')
}
function playCanvas(srcvideo, ctx) {
ctx.drawImage(srcvideo, 0, 0, 640, 360)
for (var i = 0; i < drawArray.length; i++) {
ctx.beginPath();
const xFraction = drawArray[i].x / 640;
const yFraction = drawArray[i].y / 360;
const r = 255 * (1 - xFraction);
const g = 255 * yFraction;
const b = 255 * xFraction * (1 - yFraction);
ctx.fillStyle = `rgba(${r|0}, ${g|0}, ${b|0}, 1)`;
ctx.arc(drawArray[i].x, drawArray[i].y, 10, 0, 2 * Math.PI);
ctx.fill();
}
requestAnimationFrame(() => {
playCanvas(srcvideo, ctx)
})
}
function setFormatSelect(format){
if(!MediaRecorder.isTypeSupported(format)){
alert(format)
alert("当前浏览器不支持该编码类型");
return;
}
allChunks = [];
setRecorder(format)
}
function setShowConsole(checkbox){
if ( checkbox.checked == true){
showDataAvailable = true;
}else{
showDataAvailable = false;
}
}
function setRecorder(format) {
const stream = canvas.captureStream(60); // 60 FPS recording
const recorder = new MediaRecorder(stream, {
mimeType: format
});
recorder.ondataavailable = e => {
if(showDataAvailable){
console.log("trigger ondataavailable")
}
allChunks.push(
e.data
);
}
startBtn.disabled = false;
startBtn.onclick = e => {
recorder.start(10);
startBtn.disabled = true;
pauseBtn.disabled = false;
resumeBtn.disabled = true;
stopBtn.disabled = false;
}
stopBtn.onclick = e => {
recorder.stop();
blobDownload(format);
startBtn.disabled = false;
pauseBtn.disabled = true;
resumeBtn.disabled = true;
stopBtn.disabled = true;
}
pauseBtn.onclick = e => {
recorder.pause();
pauseBtn.disabled = true;
resumeBtn.disabled = false;
}
resumeBtn.onclick = e => {
recorder.resume();
pauseBtn.disabled = false;
resumeBtn.disabled = true;
}
}
function blobDownload(format) {
const link = document.createElement('a');
link.style.display = 'none';
const fullBlob = new Blob(allChunks);
const downloadUrl = window.URL.createObjectURL(fullBlob);
link.href = downloadUrl;
link.download = 'media - '+format+'.mp4';
document.body.appendChild(link);
link.click();
link.remove();
}
</script>