Now you can select input devices
This commit is contained in:
parent
1fe0b35757
commit
0cc7fcb945
|
@ -35,8 +35,7 @@ class Convulse {
|
||||||
|
|
||||||
document.querySelector("canvas").addEventListener("click", e => this.rec(e))
|
document.querySelector("canvas").addEventListener("click", e => this.rec(e))
|
||||||
document.querySelector("#rec").addEventListener("click", e => this.rec(e))
|
document.querySelector("#rec").addEventListener("click", e => this.rec(e))
|
||||||
//document.querySelector("#save").addEventListener("click", e => this.save(e))
|
|
||||||
|
|
||||||
document.querySelector("#webcam-size").addEventListener("input", e => this.setWebcamSize(e))
|
document.querySelector("#webcam-size").addEventListener("input", e => this.setWebcamSize(e))
|
||||||
document.querySelector("#webcam-size").value = localStorage.webcamSize || 0.3
|
document.querySelector("#webcam-size").value = localStorage.webcamSize || 0.3
|
||||||
document.querySelector("#webcam-size").dispatchEvent(new Event("input"))
|
document.querySelector("#webcam-size").dispatchEvent(new Event("input"))
|
||||||
|
@ -51,19 +50,34 @@ class Convulse {
|
||||||
|
|
||||||
this.recorder = {state: "unstarted"}
|
this.recorder = {state: "unstarted"}
|
||||||
|
|
||||||
|
// this.mediaStream gets audio directly from the device, video from canvas
|
||||||
this.mediaStream = new MediaStream()
|
this.mediaStream = new MediaStream()
|
||||||
|
|
||||||
navigator.mediaDevices.getUserMedia({video: true, audio: true})
|
// Populate select boxes with what media is available
|
||||||
.then(media => {
|
navigator.mediaDevices.enumerateDevices()
|
||||||
document.querySelector("#hello").classList.add("hidden")
|
.then(devs => {
|
||||||
this.webcamVideo.muted = true
|
for (let dev of devs) {
|
||||||
this.webcamVideo.srcObject = media
|
let opt = document.createElement("option")
|
||||||
this.webcamVideo.play()
|
opt.value = dev.deviceId
|
||||||
for (let at of media.getAudioTracks()) {
|
if (dev.kind == "audioinput") {
|
||||||
this.mediaStream.addTrack(at)
|
opt.text = dev.label || `Microphone ${aud.length+1}`
|
||||||
console.log("Adding audio track", at)
|
aud.appendChild(opt)
|
||||||
|
} else if (dev.kind == "videoinput") {
|
||||||
|
opt.text = dev.label || `Camera ${vid.length+1}`
|
||||||
|
vid.appendChild(opt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Pretend the user clicked whatever's in those boxes
|
||||||
|
let aud = document.querySelector("#audio-in")
|
||||||
|
let vid = document.querySelector("#video-in")
|
||||||
|
aud.addEventListener("change", e => this.inputSelect(e))
|
||||||
|
vid.addEventListener("change", e => this.inputSelect(e))
|
||||||
|
this.inputSelect()
|
||||||
|
|
||||||
|
navigator.mediaDevices.getUserMedia({video: true, audio: true})
|
||||||
|
.then(media => this.gotUserMedia(media))
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
toast("Couldn't open camera!")
|
toast("Couldn't open camera!")
|
||||||
})
|
})
|
||||||
|
@ -81,7 +95,6 @@ class Convulse {
|
||||||
let canvasStream = this.canvas.captureStream(30)
|
let canvasStream = this.canvas.captureStream(30)
|
||||||
for (let vt of canvasStream.getVideoTracks()) {
|
for (let vt of canvasStream.getVideoTracks()) {
|
||||||
this.mediaStream.addTrack(vt)
|
this.mediaStream.addTrack(vt)
|
||||||
console.log("Adding video track", vt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.frame()
|
this.frame()
|
||||||
|
@ -89,6 +102,52 @@ class Convulse {
|
||||||
toast("Click anywhere to start and stop recording")
|
toast("Click anywhere to start and stop recording")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gotUserMedia(media) {
|
||||||
|
document.querySelector("#hello").classList.add("hidden")
|
||||||
|
|
||||||
|
// Set video source
|
||||||
|
// sending this to an HTML element seems janky, is there no direct method for video?
|
||||||
|
if (this.webcamVideo.srcObject) {
|
||||||
|
for (let track of this.webcamVideo.srcObject.getTracks()) {
|
||||||
|
track.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let track of media.getVideoTracks()) {
|
||||||
|
for (let opt of document.querySelector("#video-in")) {
|
||||||
|
if (opt.text == track.label) {
|
||||||
|
opt.selected = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.webcamVideo.muted = true
|
||||||
|
this.webcamVideo.srcObject = media
|
||||||
|
this.webcamVideo.play()
|
||||||
|
|
||||||
|
// Set audio source
|
||||||
|
for (let track of this.mediaStream.getAudioTracks()) {
|
||||||
|
this.mediaStream.removeTrack(track)
|
||||||
|
track.stop()
|
||||||
|
}
|
||||||
|
for (let track of media.getAudioTracks()) {
|
||||||
|
this.mediaStream.addTrack(track)
|
||||||
|
for (let opt of document.querySelector("#audio-in")) {
|
||||||
|
opt.selected = (opt.value == track.deviceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inputSelect(event) {
|
||||||
|
let audName = document.querySelector("#audio-in").value || undefined
|
||||||
|
let vidName = document.querySelector("#video-in").value || undefined
|
||||||
|
let constraints = {
|
||||||
|
audio: {deviceId: {exact: audName}},
|
||||||
|
video: {deviceId: {exact: vidName}}
|
||||||
|
}
|
||||||
|
|
||||||
|
navigator.mediaDevices.getUserMedia(constraints)
|
||||||
|
.then(e => this.gotUserMedia(e))
|
||||||
|
}
|
||||||
|
|
||||||
setWebcamSize(event) {
|
setWebcamSize(event) {
|
||||||
this.webcamSize = event.target.value
|
this.webcamSize = event.target.value
|
||||||
localStorage.webcamSize = this.webcamSize
|
localStorage.webcamSize = this.webcamSize
|
||||||
|
|
|
@ -38,6 +38,10 @@
|
||||||
<button id="rec">⏺️</button>
|
<button id="rec">⏺️</button>
|
||||||
<a id="save">💾</a>
|
<a id="save">💾</a>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span>🎙️<select id="audio-in"></select></span>
|
||||||
|
<span>🎥<select id="video-in"></select></span>
|
||||||
|
</div>
|
||||||
<div id="webcam-controls">
|
<div id="webcam-controls">
|
||||||
UR FACE
|
UR FACE
|
||||||
<input id="webcam-size" type="range" min="0" max="1" step="0.01" value="0.2">
|
<input id="webcam-size" type="range" min="0" max="1" step="0.01" value="0.2">
|
||||||
|
|
|
@ -1,26 +1,51 @@
|
||||||
var cacheName = "convulse-v1";
|
// jshint asi:true
|
||||||
|
|
||||||
|
var cacheName = "v2";
|
||||||
var content = [
|
var content = [
|
||||||
"index.html",
|
"index.html",
|
||||||
"convulse.css",
|
"convulse.css",
|
||||||
"convulse.js",
|
"convulse.js",
|
||||||
"convulse.png"
|
"convulse.png"
|
||||||
];
|
]
|
||||||
|
|
||||||
|
|
||||||
self.addEventListener("install", e => {
|
self.addEventListener("install", preCache)
|
||||||
e.waitUntil(caches.Open(cacheName).then(cache => cache.addAll(content)));
|
self.addEventListener("fetch", cachingFetch)
|
||||||
});
|
self.addEventListener("activate", handleActivate)
|
||||||
|
|
||||||
// Have mercy, this is a horror show
|
function handleActivate(event){
|
||||||
self.addEventListener("fetch", e => {
|
event.waitUntil(
|
||||||
e.respondWith(
|
cleanup()
|
||||||
caches.match(e.request).then(r => {
|
)
|
||||||
return r || fetch(e.request).then(response => {
|
}
|
||||||
return caches.open(cacheName).then(cache => {
|
|
||||||
cache.put(e.request, response.clone());
|
async function cleanup(event) {
|
||||||
return response;
|
let cacheNames = await caches.keys()
|
||||||
});
|
for (let name of cacheNames) {
|
||||||
});
|
if (name != cacheName) {
|
||||||
|
console.log("Deleting old cache", name)
|
||||||
|
caches.delete(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function preCache(event) {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.open(cacheName)
|
||||||
|
.then(cache => cache.addAll(content))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go try to pull a newer version from the network,
|
||||||
|
// but return what's in the cache for this request
|
||||||
|
function cachingFetch(event) {
|
||||||
|
fetch(event.request)
|
||||||
|
.then(resp => {
|
||||||
|
caches.open(cacheName)
|
||||||
|
.then(cache => {
|
||||||
|
cache.put(event.request, resp.clone())
|
||||||
})
|
})
|
||||||
);
|
})
|
||||||
});
|
|
||||||
|
event.respondWith(caches.match(event.request))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue