瀏覽代碼

Nicer media option handling

master
Roderic Day 5 年之前
父節點
當前提交
caf35969ac
共有 2 個檔案被更改,包括 25 行新增8 行删除
  1. +3
    -1
      pico.css
  2. +22
    -7
      pico.js

+ 3
- 1
pico.css 查看文件

} }
video { video {
width: 120px; width: 120px;
transform: scaleX(-1);
background-color: black; background-color: black;
} }
video.mirrored {
transform: scaleX(-1);
}

+ 22
- 7
pico.js 查看文件

const scrollIntoView = (vnode) => { const scrollIntoView = (vnode) => {
vnode.dom.scrollIntoView() vnode.dom.scrollIntoView()
} }
const toggleFullscreen = (el) => (event) => {
document.fullscreenElement ? document.exitFullscreen() : el.requestFullscreen()
}
const prettyTime = (ts) => { const prettyTime = (ts) => {
const dt = new Date(ts) const dt = new Date(ts)
const H = `0${dt.getHours()}`.slice(-2) const H = `0${dt.getHours()}`.slice(-2)
dom.autoplay = true dom.autoplay = true
dom.muted = (username === State.username) dom.muted = (username === State.username)
dom.srcObject = stream dom.srcObject = stream
dom.ondblclick = toggleFullscreen(dom)
}, },
view({attrs}) { view({attrs}) {
const rpc = State.rpcs[attrs.username] || {iceConnectionState: m.trust(' ')} const rpc = State.rpcs[attrs.username] || {iceConnectionState: m.trust(' ')}
return m('.video-container', return m('.video-container',
m('.video-source', attrs.username), m('.video-source', attrs.username),
m('.video-state', rpc.iceConnectionState), m('.video-state', rpc.iceConnectionState),
m('video', {playsinline: true, oncreate: Video.appendStream(attrs)}),
m('video.mirrored', {playsinline: true, oncreate: Video.appendStream(attrs)}),
) )
}, },
} }
const audio = {
noiseSuppresion: true,
echoCancellation: true,
}
const Media = { const Media = {
audioVideo: {audio: true, video: {width: {ideal: 320}, facingMode: 'user'}},
audioOnly: {audio: true, video: false},
turnOn: (constraints) => async () => {
options: {
video: {audio, video: {width: {ideal: 320}, facingMode: 'user'}},
audio: {audio, video: false},
screen: {audio, video: {mediaSource: 'screen'}},
none: {audio: false, video: false},
},
turnOn: async () => {
const constraints = Media.options[document.querySelector('#media-source').value]
const media = await navigator.mediaDevices.getUserMedia(constraints) const media = await navigator.mediaDevices.getUserMedia(constraints)
State.media[State.username] = media State.media[State.username] = media
wire({kind: 'peerInfo', value: {type: 'request'}}) wire({kind: 'peerInfo', value: {type: 'request'}})
view() { view() {
if(!State.media[State.username]) { if(!State.media[State.username]) {
return m('.media', return m('.media',
m('button', {onclick: Media.turnOn(Media.audioVideo)}, 'turn media on'),
m('button', {onclick: Media.turnOn(Media.audioOnly)}, 'turn audio on'),
m('button', {onclick: Media.turnOn}, 'turn on'),
m('select#media-source',
Object.keys(Media.options).map(description => m('option', description)),
),
) )
} }
else { else {
return m('.media', return m('.media',
m('button', {onclick: Media.turnOff}, 'turn media off'),
m('button', {onclick: Media.turnOff}, 'turn off'),
m('.videos', m('.videos',
Object.entries(State.media).map(([username, stream]) => Object.entries(State.media).map(([username, stream]) =>
m(Video, {username, stream}) m(Video, {username, stream})

Loading…
取消
儲存