parent
ae544add07
commit
3c87a375c3
After Width: | Height: | Size: 539 B |
@ -0,0 +1,124 @@ |
|||||||
|
<template> |
||||||
|
<div class="vid_main"> |
||||||
|
<video ref="feed_video" width="100%" height="100%" autoplay playsinline/> |
||||||
|
<div class="info">{{ bitrate }}</div> |
||||||
|
<div class="actions"></div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
props: { |
||||||
|
janusInit: Object, |
||||||
|
opaqueId: String, |
||||||
|
room: Number, |
||||||
|
mypvtid: String, |
||||||
|
feedid: String |
||||||
|
}, |
||||||
|
name: "RemoteFeed", |
||||||
|
data: () => ({ |
||||||
|
remoteFeed: null, |
||||||
|
bitrateTimer: null, |
||||||
|
bitrate: 0 |
||||||
|
}), |
||||||
|
mounted () { |
||||||
|
console.log(this.janusInit) |
||||||
|
this.janusInit.attach({ |
||||||
|
plugin: "janus.plugin.videoroom", |
||||||
|
opaqueId: this.opaqueId, |
||||||
|
success: this.onSuccess, |
||||||
|
onmessage: this.onMessage, |
||||||
|
error: function(error) { |
||||||
|
console.log(" -- Error attaching plugin...", error); |
||||||
|
// bootbox.alert("Error attaching plugin... " + error); |
||||||
|
}, |
||||||
|
webrtcState: function(on) { |
||||||
|
console.log("Janus says this WebRTC PeerConnection " + (on ? "up" : "down") + " now"); |
||||||
|
}, |
||||||
|
onlocalstream: this.onlocalstream, |
||||||
|
onremotestream: this.onStream |
||||||
|
|
||||||
|
}) |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
onSuccess (pluginHandle) { |
||||||
|
this.remoteFeed = pluginHandle; |
||||||
|
this.remoteFeed.simulcastStarted = false; |
||||||
|
console.log('Remote feed success') |
||||||
|
var subscribe = { "request": "join", "room": this.room, "ptype": "subscriber", "feed": this.feedid, "private_id": this.mypvtid }; |
||||||
|
|
||||||
|
this.remoteFeed.send({"message": subscribe}); |
||||||
|
|
||||||
|
}, |
||||||
|
onlocalstream (locals) { |
||||||
|
console.log(locals) |
||||||
|
}, |
||||||
|
onStream (stream) { |
||||||
|
console.log('stream is strarted') |
||||||
|
|
||||||
|
this.$refs.feed_video.srcObject = stream |
||||||
|
setInterval(() => { |
||||||
|
this.bitrate = this.remoteFeed.getBitrate() |
||||||
|
},1000) |
||||||
|
}, |
||||||
|
feedResponse (jsep) { |
||||||
|
var body = { "request": "start", "room": this.room } |
||||||
|
this.remoteFeed.send({"message": body, "jsep": jsep}) |
||||||
|
}, |
||||||
|
feedError (error) { |
||||||
|
console.log("WebRTC error:", error) |
||||||
|
}, |
||||||
|
onMessage (msg, jsep) { |
||||||
|
console.log(msg) |
||||||
|
console.log(jsep) |
||||||
|
console.log("-------------------------") |
||||||
|
var event = msg["videoroom"]; |
||||||
|
if(msg["error"] !== undefined && msg["error"] !== null) { |
||||||
|
console.log(msg["error"]); |
||||||
|
} else if(event !== undefined && event != null) { |
||||||
|
this.remoteFeed.rfid = msg["id"] |
||||||
|
this.remoteFeed.rfdisplay = msg["display"] |
||||||
|
|
||||||
|
} else if(event === "event") { |
||||||
|
var substream = msg["substream"] |
||||||
|
var temporal = msg["temporal"] |
||||||
|
console.log(substream,temporal) |
||||||
|
} |
||||||
|
if(jsep !== undefined && jsep !== null) { |
||||||
|
console.log('jsep') |
||||||
|
console.log(jsep) |
||||||
|
this.remoteFeed.createAnswer( |
||||||
|
{ |
||||||
|
jsep: jsep, |
||||||
|
// Add data:true here if you want to subscribe to datachannels as well |
||||||
|
// (obviously only works if the publisher offered them in the first place) |
||||||
|
media: { audioSend: false, videoSend: false }, // We want recvonly audio/video |
||||||
|
success: this.feedResponse, |
||||||
|
error: this.feedError |
||||||
|
}); |
||||||
|
} |
||||||
|
}, |
||||||
|
onError (error) { |
||||||
|
console.log(error) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.actions { |
||||||
|
position: absolute; |
||||||
|
bottom:0; |
||||||
|
left:0; |
||||||
|
} |
||||||
|
.vid_main { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
.info { |
||||||
|
position: absolute; |
||||||
|
right: 0; |
||||||
|
top:0; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,279 @@ |
|||||||
|
<template> |
||||||
|
<v-container> |
||||||
|
<v-dialog |
||||||
|
v-model="deviceSelectDialog" |
||||||
|
max-width="290" |
||||||
|
> |
||||||
|
<v-card> |
||||||
|
<v-card-title class="headline">Configuration</v-card-title> |
||||||
|
|
||||||
|
<v-card-text> |
||||||
|
<v-row> |
||||||
|
<v-col md="12" cols="12"> |
||||||
|
<v-select |
||||||
|
label="Please select video device" |
||||||
|
v-model="selectedVideo" |
||||||
|
:items="videoDevices" |
||||||
|
item-value="deviceId" |
||||||
|
item-text="label" |
||||||
|
></v-select> |
||||||
|
</v-col> |
||||||
|
<v-col md="12" cols="12"> |
||||||
|
<v-select |
||||||
|
label="Please select audio device" |
||||||
|
:items="audioDevices" |
||||||
|
v-model="selectedAudio" |
||||||
|
item-value="deviceId" |
||||||
|
item-text="label" |
||||||
|
></v-select> |
||||||
|
</v-col> |
||||||
|
</v-row> |
||||||
|
</v-card-text> |
||||||
|
|
||||||
|
<v-card-actions> |
||||||
|
<v-spacer></v-spacer> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
color="green darken-1" |
||||||
|
text |
||||||
|
@click="deviceSelectDialog = false" |
||||||
|
> |
||||||
|
Disagree |
||||||
|
</v-btn> |
||||||
|
|
||||||
|
<v-btn |
||||||
|
color="green darken-1" |
||||||
|
text |
||||||
|
@click="selectDevice" |
||||||
|
> |
||||||
|
Agree |
||||||
|
</v-btn> |
||||||
|
</v-card-actions> |
||||||
|
</v-card> |
||||||
|
</v-dialog> |
||||||
|
<v-btn @click="genRemoteFeed">Remote Feed</v-btn> |
||||||
|
<v-row> |
||||||
|
<v-col cols="12" md="3"> |
||||||
|
<video ref="ownstream" class="rounded centered" id="myvideo" width="100%" height="100%" autoplay |
||||||
|
playsinline muted="muted"/> |
||||||
|
</v-col> |
||||||
|
<v-col cols="12" md="3" v-for="remoteStream in remoteStreams" :key="remoteStream.id"> |
||||||
|
<RemoteFeed :opaqueId="opaqueId" :mypvtid="mypvtid" :feedid="remoteStream.id" :janusInit="janusInit" :room="room" ></RemoteFeed> |
||||||
|
</v-col> |
||||||
|
</v-row> |
||||||
|
</v-container> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
|
||||||
|
import RemoteFeed from "@/lib/RemoteFeed"; |
||||||
|
export default { |
||||||
|
components: {RemoteFeed}, |
||||||
|
props: { |
||||||
|
server: String, |
||||||
|
room: Number, |
||||||
|
username: String |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
janusInit: null, |
||||||
|
opaqueId: null, |
||||||
|
pluginHandle: null, |
||||||
|
mystream: null, |
||||||
|
myid: '', |
||||||
|
mypvtid: '', |
||||||
|
selectedVideo: null, |
||||||
|
selectedAudio: null, |
||||||
|
videoDevices: [], |
||||||
|
audioDevices: [], |
||||||
|
deviceSelectDialog: false, |
||||||
|
remoteStreams: [] |
||||||
|
} |
||||||
|
}, |
||||||
|
name: "VueJanus", |
||||||
|
mounted() { |
||||||
|
this.janusInit = new this.$janus({ |
||||||
|
success: this.janusSuccess, |
||||||
|
server: this.server, |
||||||
|
error: function (error) { |
||||||
|
this.$janus.error(error); |
||||||
|
}, |
||||||
|
destroyed: function () { |
||||||
|
window.location.reload(); |
||||||
|
} |
||||||
|
}) |
||||||
|
|
||||||
|
}, |
||||||
|
methods: { |
||||||
|
janusPluginError: function (error) { |
||||||
|
console.log(error) |
||||||
|
}, |
||||||
|
consentDialog: function (on) { |
||||||
|
// this.$janus.debug("Consent dialog should be " + (on ? "on" : "off") + " now"); |
||||||
|
console.log(on) |
||||||
|
}, |
||||||
|
janusPluginSuccess: function (pluginHandle) { |
||||||
|
this.pluginHandle = pluginHandle |
||||||
|
this.$janus.log("Plugin attached! (" + this.pluginHandle.getPlugin() + ", id=" + this.pluginHandle.getId() + ")"); |
||||||
|
this.$janus.log(" -- This is a publisher/manager"); |
||||||
|
|
||||||
|
this.$janus.listDevices(this.initDevices); |
||||||
|
|
||||||
|
|
||||||
|
}, |
||||||
|
initDevices: function (devices) { |
||||||
|
console.log(devices) |
||||||
|
devices.forEach(device => { |
||||||
|
if (device.kind === 'videoinput') { |
||||||
|
this.videoDevices.push(device) |
||||||
|
} |
||||||
|
if (device.kind === 'audioinput') { |
||||||
|
this.audioDevices.push(device) |
||||||
|
} |
||||||
|
|
||||||
|
}) |
||||||
|
this.deviceSelectDialog = true |
||||||
|
}, |
||||||
|
genRemoteFeed: function () { |
||||||
|
this.remoteStreams.forEach(item => { |
||||||
|
this.createRemoteFeed(item) |
||||||
|
}) |
||||||
|
}, |
||||||
|
offerSend: function (jsep) { |
||||||
|
console.log('vid offer') |
||||||
|
var publish = {"request": "configure", "audio": true, "video": true}; |
||||||
|
|
||||||
|
this.pluginHandle.send({"message": publish, "jsep": jsep}); |
||||||
|
}, |
||||||
|
controlPublishers: function(msg) { |
||||||
|
msg["publishers"].forEach(item => { |
||||||
|
var has = false |
||||||
|
this.remoteStreams.forEach(rm => { |
||||||
|
if (item.id === rm.id) has = true |
||||||
|
}) |
||||||
|
if (!has) { |
||||||
|
this.remoteStreams.push(item) |
||||||
|
} |
||||||
|
|
||||||
|
}) |
||||||
|
}, |
||||||
|
janusMessage: function (msg, jsep) { |
||||||
|
// this.$janus.debug(" ::: Got a message (publisher) :::"); |
||||||
|
console.log(msg); |
||||||
|
// this.$janus.debug(jsep); |
||||||
|
var event = msg["videoroom"]; |
||||||
|
// this.$janus.debug("Event: " + event); |
||||||
|
if (event !== undefined) { |
||||||
|
if (event === "joined") { |
||||||
|
this.myid = msg["id"]; |
||||||
|
this.mypvtid = msg["private_id"]; |
||||||
|
this.$janus.log("Successfully joined room " + msg["room"] + " with ID " + this.myid); |
||||||
|
this.restartDevices() |
||||||
|
if (msg["publishers"] !== undefined && msg["publishers"] !== null) { |
||||||
|
this.controlPublishers(msg) |
||||||
|
} |
||||||
|
} else if(event === "event") { |
||||||
|
// Any new feed to attach to? |
||||||
|
if (msg["publishers"] !== undefined && msg["publishers"] !== null) { |
||||||
|
this.controlPublishers(msg) |
||||||
|
|
||||||
|
} else if(msg["leaving"] !== undefined && msg["leaving"] !== null) { |
||||||
|
console.log("leaving") |
||||||
|
this.remoteStreams.forEach(item => { |
||||||
|
if (item.id === msg['leaving']) this.remoteStreams.splice(this.remoteStreams.indexOf(item),1) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (jsep !== undefined && jsep !== null) { |
||||||
|
|
||||||
|
console.log("Handling SDP as well..."); |
||||||
|
console.log(jsep); |
||||||
|
this.pluginHandle.handleRemoteJsep({jsep: jsep}); |
||||||
|
var audio = msg["audio_codec"]; |
||||||
|
if (this.mystream && this.mystream.getAudioTracks() && this.mystream.getAudioTracks().length > 0 && !audio) { |
||||||
|
// Audio has been rejected |
||||||
|
//toastr.warning("Our audio stream has been rejected, viewers won't hear us"); |
||||||
|
console.log("Our audio stream has been rejected, viewers won't hear us"); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
onlocalstream: function (stream) { |
||||||
|
// this.$janus.debug(" ::: Got a local stream :::"); |
||||||
|
// this.$janus.debug(stream); |
||||||
|
this.mystream = stream |
||||||
|
console.log(this.$refs) |
||||||
|
console.log(this.$refs["ownstream"]) |
||||||
|
this.$refs.ownstream.srcObject = this.mystream |
||||||
|
|
||||||
|
}, |
||||||
|
restartDevices: function () { |
||||||
|
this.deviceSelectDialog = false |
||||||
|
|
||||||
|
var media = { |
||||||
|
audioRecv: false, videoRecv: false, audioSend: true, videoSend: true, |
||||||
|
audio: { |
||||||
|
deviceId: { |
||||||
|
exact: this.selectedAudio |
||||||
|
} |
||||||
|
}, |
||||||
|
replaceAudio: true, // This is only needed in case of a renegotiation |
||||||
|
video: { |
||||||
|
deviceId: { |
||||||
|
exact: this.selectedVideo |
||||||
|
} |
||||||
|
}, |
||||||
|
replaceVideo: true, |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
this.pluginHandle.createOffer( |
||||||
|
{ |
||||||
|
media: media, |
||||||
|
success: this.offerSend, |
||||||
|
error: function (error) { |
||||||
|
// An error has occurred ... |
||||||
|
console.log(error) |
||||||
|
} |
||||||
|
}) |
||||||
|
}, |
||||||
|
webrtcState: function (on) { |
||||||
|
this.$janus.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now"); |
||||||
|
}, |
||||||
|
mediaState: function (medium, on) { |
||||||
|
this.$janus.log("Janus " + (on ? "started" : "stopped") + " receiving our " + medium); |
||||||
|
}, |
||||||
|
selectDevice: function () { |
||||||
|
console.log(this.selectedVideo) |
||||||
|
console.log(this.selectedAudio) |
||||||
|
// this.$refs.ownstream.setSinkId(this.selectedVideo) |
||||||
|
// this.$refs.ownstream.setSinkId(this.selectedAudio) |
||||||
|
|
||||||
|
var register = {"request": "join", "room": this.room, "ptype": "publisher", "display": this.username}; |
||||||
|
this.pluginHandle.send({"message": register}); |
||||||
|
}, |
||||||
|
janusSuccess: function () { |
||||||
|
this.opaqueId = "videoroomtest-" + this.$janus.randomString(12); |
||||||
|
|
||||||
|
this.janusInit.attach( |
||||||
|
{ |
||||||
|
plugin: "janus.plugin.videoroom", |
||||||
|
opaqueId: this.opaqueId, |
||||||
|
success: this.janusPluginSuccess, |
||||||
|
consentDialog: this.consentDialog, |
||||||
|
error: this.janusPluginError, |
||||||
|
mediaState: this.mediaState, |
||||||
|
webrtcState: this.webrtcState, |
||||||
|
onmessage: this.janusMessage, |
||||||
|
onlocalstream: this.onlocalstream |
||||||
|
} |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,14 @@ |
|||||||
import Vue from 'vue' |
import Vue from 'vue' |
||||||
|
import './plugins/axios' |
||||||
|
import JanusPlugin from "@/plugins/janus" |
||||||
import App from './App.vue' |
import App from './App.vue' |
||||||
|
import vuetify from './plugins/vuetify'; |
||||||
|
|
||||||
Vue.config.productionTip = false |
|
||||||
|
|
||||||
|
Vue.config.productionTip = false |
||||||
|
console.log("janus is installed", Vue.$janus) |
||||||
new Vue({ |
new Vue({ |
||||||
render: h => h(App), |
vuetify, |
||||||
|
JanusPlugin, |
||||||
|
render: h => h(App) |
||||||
}).$mount('#app') |
}).$mount('#app') |
||||||
|
@ -0,0 +1,62 @@ |
|||||||
|
"use strict"; |
||||||
|
|
||||||
|
import Vue from 'vue'; |
||||||
|
import axios from "axios"; |
||||||
|
|
||||||
|
// Full config: https://github.com/axios/axios#request-config
|
||||||
|
// axios.defaults.baseURL = process.env.baseURL || process.env.apiUrl || '';
|
||||||
|
// axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
|
||||||
|
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||||
|
|
||||||
|
let config = { |
||||||
|
// baseURL: process.env.baseURL || process.env.apiUrl || ""
|
||||||
|
// timeout: 60 * 1000, // Timeout
|
||||||
|
// withCredentials: true, // Check cross-site Access-Control
|
||||||
|
}; |
||||||
|
|
||||||
|
const _axios = axios.create(config); |
||||||
|
|
||||||
|
_axios.interceptors.request.use( |
||||||
|
function(config) { |
||||||
|
// Do something before request is sent
|
||||||
|
return config; |
||||||
|
}, |
||||||
|
function(error) { |
||||||
|
// Do something with request error
|
||||||
|
return Promise.reject(error); |
||||||
|
} |
||||||
|
); |
||||||
|
|
||||||
|
// Add a response interceptor
|
||||||
|
_axios.interceptors.response.use( |
||||||
|
function(response) { |
||||||
|
// Do something with response data
|
||||||
|
return response; |
||||||
|
}, |
||||||
|
function(error) { |
||||||
|
// Do something with response error
|
||||||
|
return Promise.reject(error); |
||||||
|
} |
||||||
|
); |
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
Plugin.install = function(Vue, options) { |
||||||
|
Vue.axios = _axios; |
||||||
|
window.axios = _axios; |
||||||
|
Object.defineProperties(Vue.prototype, { |
||||||
|
axios: { |
||||||
|
get() { |
||||||
|
return _axios; |
||||||
|
} |
||||||
|
}, |
||||||
|
$axios: { |
||||||
|
get() { |
||||||
|
return _axios; |
||||||
|
} |
||||||
|
}, |
||||||
|
}); |
||||||
|
}; |
||||||
|
|
||||||
|
Vue.use(Plugin) |
||||||
|
|
||||||
|
export default Plugin; |
@ -0,0 +1,21 @@ |
|||||||
|
"use strict"; |
||||||
|
|
||||||
|
import Vue from 'vue' |
||||||
|
import Janus from "@/lib/janus" |
||||||
|
const _janus = Janus |
||||||
|
|
||||||
|
const JanusPlugin = { |
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
install(Vue, options) { |
||||||
|
console.log('install call') |
||||||
|
console.log(_janus) |
||||||
|
_janus.init({debug: true, callback: function() { |
||||||
|
Vue.prototype.$janus = _janus |
||||||
|
}}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default JanusPlugin; |
||||||
|
Vue.use(JanusPlugin) |
@ -0,0 +1,23 @@ |
|||||||
|
import Vue from 'vue'; |
||||||
|
import Vuetify from 'vuetify/lib'; |
||||||
|
|
||||||
|
Vue.use(Vuetify); |
||||||
|
|
||||||
|
export default new Vuetify({ |
||||||
|
theme: { |
||||||
|
options: { |
||||||
|
customProperties: true, |
||||||
|
}, |
||||||
|
themes: { |
||||||
|
light: { |
||||||
|
primary: '#ee44aa', |
||||||
|
secondary: '#424242', |
||||||
|
accent: '#82B1FF', |
||||||
|
error: '#FF5252', |
||||||
|
info: '#2196F3', |
||||||
|
success: '#4CAF50', |
||||||
|
warning: '#FFC107' |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}); |
@ -0,0 +1,5 @@ |
|||||||
|
module.exports = { |
||||||
|
"transpileDependencies": [ |
||||||
|
"vuetify" |
||||||
|
] |
||||||
|
} |
Loading…
Reference in new issue