Created
September 23, 2018 02:42
-
-
Save madeinfree/864ab5438f8b3a41687accd17d61748f to your computer and use it in GitHub Desktop.
use HTML5 MediaRecord API and SocketIO to build a simple voice room
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | |
<title>Document</title> | |
</head> | |
<body> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js'></script> | |
<script> | |
const socket = io('ws://localhost:8080'); | |
const body = document.body | |
if (navigator.mediaDevices) { | |
const constraints = { audio: true } | |
const chunks = [] | |
const work = async () => { | |
const buttonBlock = document.createElement('div') | |
const startBtn = document.createElement('button') | |
startBtn.textContent = '按著錄音' | |
startBtn.style.border = '1px solid #ccc' | |
startBtn.style.borderRadius = '3px' | |
buttonBlock.appendChild(startBtn) | |
body.appendChild(buttonBlock) | |
const stream = await navigator.mediaDevices.getUserMedia(constraints).then(stream => stream) | |
const mediaRecord = new MediaRecorder(stream) | |
startBtn.onmousedown = () => { | |
mediaRecord.start(); | |
startBtn.textContent = '錄音中...' | |
} | |
startBtn.onmouseup = () => { | |
mediaRecord.stop() | |
startBtn.textContent = '按著錄音' | |
} | |
body.appendChild(document.createElement('br')) | |
mediaRecord.onstop = (e) => { | |
const blob = new Blob(chunks, { 'type': 'video/webm; codecs=opus' }) | |
// to ArrayBuffer | |
const fr = new FileReader() | |
let uint8ArrayNew = null | |
fr.onload = (e) => { | |
uint8ArrayNew = new Uint8Array(e.target.result) | |
fetch('http://127.0.0.1:8080', { | |
method: 'POST', | |
body: uint8ArrayNew | |
}).then(response => { | |
console.log('send success..') | |
}) | |
chunks.length = 0 | |
} | |
fr.readAsArrayBuffer(blob) | |
} | |
mediaRecord.ondataavailable = (e) => { | |
chunks.push(e.data) | |
} | |
} | |
work() | |
socket.on('new-voice', (msg) => { | |
const fragment = document.createDocumentFragment() | |
const block = document.createElement('div') | |
const audio = document.createElement('audio'); | |
const date = document.createElement('span') | |
const now = new Date() | |
date.textContent = now | |
audio.setAttribute('controls', '') | |
block.appendChild(audio) | |
block.appendChild(date) | |
fragment.appendChild(block) | |
body.appendChild(fragment) | |
const resBlob = new Blob([new Uint8Array(msg)], { 'type': 'audio/ogg; codecs=opus' }) | |
const audioURL = URL.createObjectURL(resBlob) | |
audio.src = audioURL | |
}) | |
socket.on('init', (msg) => { | |
console.log(msg) | |
}) | |
} | |
</script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const app = require('express')(); | |
const http = require('http').Server(app); | |
const io = require('socket.io')(http); | |
const EventEmitter = require('events'); | |
class VoiceEmitter extends EventEmitter {} | |
const voiceEmitter = new VoiceEmitter(); | |
app.post('/', (req, res) => { | |
const chunks = []; | |
res.setHeader('Access-Control-Allow-Origin', '*'); | |
req.on('data', chunk => { | |
chunks.push(chunk); | |
}); | |
req.on('end', () => { | |
// fs.writeFileSync(`./upload/${new Date().getTime()}.webm`, chunks[0]); | |
res.end('OK'); | |
voiceEmitter.emit('broadcast', chunks[0]); | |
}); | |
}); | |
voiceEmitter.on('broadcast', chunks => { | |
io.emit('new-voice', chunks); | |
}); | |
let users = new WeakMap(); | |
io.on('connection', function(socket) { | |
console.log('a user connected.'); | |
users.set(socket, { | |
id: new Date().getTime() | |
}); | |
socket.emit('init', users.get(socket).id); | |
socket.on('disconnect', reason => { | |
console.log('user disconnected.'); | |
users.delete(socket); | |
}); | |
}); | |
http.listen(8080); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "Nodejs-Media", | |
"version": "1.0.0", | |
"description": "", | |
"main": "index.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"keywords": [], | |
"author": "", | |
"license": "ISC", | |
"dependencies": { | |
"express": "^4.16.3", | |
"socket.io": "^2.1.1" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment