Now you can select input devices

This commit is contained in:
Neale Pickett 2020-03-08 12:03:22 -06:00
parent 1fe0b35757
commit 0cc7fcb945
3 changed files with 117 additions and 29 deletions

View File

@ -35,7 +35,6 @@ 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
@ -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

View File

@ -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">

View File

@ -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))
}