-
Notifications
You must be signed in to change notification settings - Fork 0
/
ghost_webcam.html
121 lines (104 loc) · 3.53 KB
/
ghost_webcam.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
<!doctype html>
<html>
<head>
<script src="three.js-master/build/three.js"></script>
<script src="dat.gui-master/build/dat.gui.js"></script>
<script src="js/temporal_smoothing.js"></script>
<title>Webcam ghost effect</title>
</head>
<body>
<nav style="position: absolute; top:0; left:0, height:2vh; z-index:999">
<a href="." style="color: #66ffff">Back to index.</a>
</nav>
<script>
var videoTexture, videoSettings, rawVideoStream, videoStream, audioTrack;
let gui = new dat.GUI();
navigator.mediaDevices.getUserMedia({video: true, audio: true}).then(function(stream) {
rawVideoStream = stream; //global reference
videoSettings = stream.getVideoTracks()[0].getSettings();
console.log("videoSettings: width=%d, height=%d, frameRate=%d",videoSettings.width,videoSettings.height, videoSettings.frameRate);
audioTrack = stream.getAudioTracks()[0];
//Making a separate pure video stream is a workaround
//let videoStream = new MediaStream(stream.getVideoTracks());
let video = document.createElement("video");
Object.assign(video, {
srcObject: stream,//videoStream,
width: videoSettings.width,
height: videoSettings.height,
autoplay: true,
//Setting muted here breaks everything
//muted: true,
});
//Toggling muted later works as expected, if muted was initially false:
gui.add(video, "muted");
//document.body.appendChild(video);
videoTexture = new THREE.VideoTexture(video);
videoTexture.minFilter = THREE.LinearFilter;
init();
}
).catch(function(error){console.error(error);});
var renderer, scene, camera, smoother;
function init() {
let w = videoSettings.width;
let h = videoSettings.height;
//Renderer setup
document.body.style = "overflow: hidden;";
var container = document.createElement("div");
document.body.appendChild(container);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(w, h);
container.appendChild(renderer.domElement);
smoother = new Smoother(videoTexture, undefined, undefined, renderer);
//gui.add(smoother, "remember", 0.01, 1, 0.01);
//gui.add(smoother, "refresh", 0, 0.99, 0.01);
gui.add({smoothing:0.95},"smoothing",0.8,0.99,0.01).onChange(function(v) {
smoother.remember = v;
smoother.refresh = 1-v;
});
//Scene setup:
/*scene = new THREE.Scene();
let display = new THREE.Mesh(
new THREE.PlaneBufferGeometry(2, 2),
new THREE.MeshBasicMaterial({map: videoTexture})
);
scene.add(display);
//Camera setup:
camera = new THREE.OrthographicCamera(-1,1,1,-1);
camera.position.z = 1;
//scene.add(camera);
*/
videoStream = renderer.domElement.captureStream(videoSettings.frameRate);
videoStream.addTrack(audioTrack);
let data, mediaRecorder;
let recording = false;
gui.add({record: function() {
if (!recording) {
data = [];
mediaRecorder = new MediaRecorder(videoStream);
//DEBUG (did not work either)
//mediaRecorder = new MediaRecorder(rawVideoStream);
console.log(mediaRecorder.mimeType);
mediaRecorder.ondataavailable = function(e) {data.push(e.data);};
mediaRecorder.onstop = function(e) {
//let blob = new Blob(data, {type: "video/webm"});
let blob = new Blob(data, {type: mediaRecorder.mimeType});
let a = document.createElement("a");
a.download = "Video_recording";//true;//"Video_recording.webm";
a.href = window.URL.createObjectURL(blob);
a.click();
}
mediaRecorder.start();
recording = true;
} else {
mediaRecorder.stop();
recording = false;
}
}},"record");
setInterval(function() {
smoother.update()
//renderer.render(scene, camera);
}, 1000./videoSettings.frameRate);
}
</script>
</body>
</html>