You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
13 KiB
324 lines
13 KiB
<template>
|
|
<div style="position: absolute;right: 0;bottom:0;width: 400px;border:1px solid #ccc">
|
|
|
|
<v-row>
|
|
<v-col cols="12" md="10">
|
|
<v-file-input ref="file" id="myfile" accept="pdf" label="Please select a file"></v-file-input>
|
|
|
|
</v-col>
|
|
<v-col cols="12" md="2">
|
|
<v-btn @click="loadFile" icon><v-icon>mdi-chevron-right</v-icon></v-btn>
|
|
|
|
</v-col>
|
|
</v-row>
|
|
<canvas style="zoom:0.3" id="mypdfview"></canvas><br />
|
|
<v-btn v-if="pdf && !loading" :disabled="pageNumber ==1" @click="prevPage" icon><v-icon>mdi-chevron-left</v-icon></v-btn>
|
|
<span v-if="pdf && !loading">{{pageNumber}} / {{pdf.numPages}}</span>
|
|
<v-btn v-if="pdf && !loading" :disabled="pdf.numPages == pageNumber" @click="nextPage" icon><v-icon>mdi-chevron-right</v-icon></v-btn>
|
|
<v-row>
|
|
<v-col cols="12" md="12">
|
|
<v-btn v-if="pdf && !loading" @click="stop">stop pdf share</v-btn>
|
|
</v-col>
|
|
</v-row>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import pdfjsLib from 'pdfjs-dist/webpack';
|
|
import WebRTCAdaptor from "@/lib/webrtc_adaptor";
|
|
const toBase64 = file => new Promise((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
reader.readAsDataURL(file);
|
|
reader.onload = () => resolve(reader.result);
|
|
reader.onerror = error => reject(error);
|
|
});
|
|
|
|
export default {
|
|
name: "PdfShare",
|
|
props: {
|
|
janusInit: Object,
|
|
onstop: Function,
|
|
username: String,
|
|
myrivid: Number,
|
|
streamer:Boolean,
|
|
room: Number,
|
|
opaqueId:String
|
|
},
|
|
data: () => ({
|
|
pdf:null,
|
|
pageNumber:1,
|
|
loading:true,
|
|
pluginHandle: null
|
|
}),
|
|
mounted () {
|
|
pdfjsLib.GlobalWorkerOptions.workerSrc = "/pdf.worker.js"
|
|
},
|
|
methods: {
|
|
streamerScreenShare(stream) {
|
|
let websocketURL = "wss://live.ozgurkon.org/LiveApp/websocket"
|
|
var mediaConstraints = {
|
|
video: { width: 1280, height: 720 },
|
|
audio: false
|
|
};
|
|
var pc_config = null;
|
|
|
|
var sdpConstraints = {
|
|
OfferToReceiveAudio: false,
|
|
OfferToReceiveVideo: false
|
|
|
|
};
|
|
if (this.streamer) {
|
|
var tt = this
|
|
this.antwrtcScreen = new WebRTCAdaptor({
|
|
websocket_url: websocketURL,
|
|
mediaConstraints: mediaConstraints,
|
|
peerconnection_config: pc_config,
|
|
sdp_constraints: sdpConstraints,
|
|
janusScreen:stream,
|
|
localVideoId: "myvideo2",
|
|
debug: true,
|
|
callback: function (info, obj) {
|
|
if (info == "initialized") {
|
|
console.log("initialized");
|
|
tt.antwrtcScreen.publish(tt.username+"-pdf", "null");
|
|
|
|
// start_publish_button.disabled = false;
|
|
// stop_publish_button.disabled = true;
|
|
} else if (info == "publish_started") {
|
|
//stream is being published
|
|
console.log("publish started");
|
|
// start_publish_button.disabled = true;
|
|
// stop_publish_button.disabled = false;
|
|
// startAnimation();
|
|
} else if (info == "publish_finished") {
|
|
//stream is being finished
|
|
console.log("publish finished");
|
|
this.startPublishing(tt.username + "-pdf");
|
|
|
|
// start_publish_button.disabled = false;
|
|
// stop_publish_button.disabled = true;
|
|
} else if (info == "screen_share_extension_available") {
|
|
// screen_share_checkbox.disabled = false;
|
|
// console.log("screen share extension available");
|
|
// install_extension_link.style.display = "none";
|
|
} else if (info == "screen_share_stopped") {
|
|
console.log("screen share stopped");
|
|
} else if (info == "closed") {
|
|
//console.log("Connection closed");
|
|
if (typeof obj != "undefined") {
|
|
console.log("Connecton closed: " + JSON.stringify(obj));
|
|
}
|
|
} else if (info == "pong") {
|
|
//ping/pong message are sent to and received from server to make the connection alive all the time
|
|
//It's especially useful when load balancer or firewalls close the websocket connection due to inactivity
|
|
} else if (info == "refreshConnection") {
|
|
this.startPublishing(tt.username + "-pdf");
|
|
} else if (info == "updated_stats") {
|
|
//obj is the PeerStats which has fields
|
|
//averageOutgoingBitrate - kbits/sec
|
|
//currentOutgoingBitrate - kbits/sec
|
|
console.log("Average outgoing bitrate " + obj.averageOutgoingBitrate + " kbits/sec"
|
|
+ " Current outgoing bitrate: " + obj.currentOutgoingBitrate + " kbits/sec");
|
|
|
|
}
|
|
},
|
|
callbackError: function (error, message) {
|
|
//some of the possible errors, NotFoundError, SecurityError,PermissionDeniedError
|
|
|
|
console.log("error callback: " + JSON.stringify(error));
|
|
var errorMessage = JSON.stringify(error);
|
|
if (typeof message != "undefined") {
|
|
errorMessage = message;
|
|
}
|
|
if (error.indexOf("NotFoundError") != -1) {
|
|
errorMessage = "Camera or Mic are not found or not allowed in your device";
|
|
} else if (error.indexOf("NotReadableError") != -1 || error.indexOf("TrackStartError") != -1) {
|
|
errorMessage = "Camera or Mic is being used by some other process that does not let read the devices";
|
|
} else if (error.indexOf("OverconstrainedError") != -1 || error.indexOf("ConstraintNotSatisfiedError") != -1) {
|
|
errorMessage = "There is no device found that fits your video and audio constraints. You may change video and audio constraints"
|
|
} else if (error.indexOf("NotAllowedError") != -1 || error.indexOf("PermissionDeniedError") != -1) {
|
|
errorMessage = "You are not allowed to access camera and mic.";
|
|
} else if (error.indexOf("TypeError") != -1) {
|
|
errorMessage = "Video/Audio is required";
|
|
}
|
|
|
|
alert(errorMessage);
|
|
}
|
|
});
|
|
}
|
|
|
|
},
|
|
renderPage(pageNumber) {
|
|
this.pdf.getPage(pageNumber).then(page => {
|
|
console.log('Page loaded');
|
|
|
|
var scale = 1.0;
|
|
var viewport = page.getViewport({scale: scale});
|
|
|
|
// Prepare canvas using PDF page dimensions
|
|
var canvas = document.getElementById('mypdfview');
|
|
var context = canvas.getContext('2d');
|
|
canvas.height = viewport.height;
|
|
canvas.width = viewport.width;
|
|
|
|
// Render PDF page into canvas context
|
|
var renderContext = {
|
|
canvasContext: context,
|
|
viewport: viewport
|
|
};
|
|
|
|
var renderTask = page.render(renderContext);
|
|
renderTask.promise.then( () => {
|
|
if (!this.pluginHandle) {
|
|
this.loading = false
|
|
// document.getElementById('pdfvid').srcObject = document.getElementById('mypdfview').captureStream(60)
|
|
|
|
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
|
|
}
|
|
)
|
|
}
|
|
});
|
|
});
|
|
},
|
|
janusPluginSuccess (pluginHandle) {
|
|
this.pluginHandle = pluginHandle
|
|
|
|
var register = { "request": "join", "room": this.room, "ptype": "publisher", "display": this.username + '- PDF' };
|
|
pluginHandle.send({"message": register});
|
|
|
|
},
|
|
stop(){
|
|
var unpublish = { "request": "unpublish"};
|
|
this.pluginHandle.send({"message": unpublish});
|
|
|
|
this.pluginHandle.detach();
|
|
|
|
// reset
|
|
this.pluginHandle = null;
|
|
this.pdf = null;
|
|
this.pageNumber = 1;
|
|
this.loading = true;
|
|
|
|
// callback
|
|
this.onstop();
|
|
},
|
|
janusPluginError (error) {
|
|
console.log('error', error)
|
|
},
|
|
consentDialog () {
|
|
|
|
},
|
|
mediaState (medium, on) {
|
|
console.log("Janus " + (on ? "started" : "stopped") + " receiving our " + medium);
|
|
},
|
|
webrtcState (on) {
|
|
this.pluginHandle.send({"message": { "request": "configure", "bitrate": 512*1000 }});
|
|
console.log(on, "webrt")
|
|
},
|
|
janusMessage (msg, jsep) {
|
|
console.log(msg)
|
|
console.log(jsep)
|
|
var event = msg["videoroom"];
|
|
if(event != undefined && event != null) {
|
|
if (event === "joined") {
|
|
this.createStream()
|
|
}
|
|
}
|
|
|
|
if(jsep !== undefined && jsep !== null) {
|
|
this.pluginHandle.handleRemoteJsep({jsep: jsep});
|
|
}
|
|
},
|
|
createStreamSuccess(jsep) {
|
|
console.log('createStreamSuccess')
|
|
var publish = { "request": "configure", "audio": false, "video": true };
|
|
this.pluginHandle.send({"message": publish, "jsep": jsep});
|
|
|
|
},
|
|
createStream() {
|
|
console.log('createStream')
|
|
|
|
this.pluginHandle.createOffer({
|
|
media: { audioRecv: false, videoRecv: false, audioSend: false, videoSend: true }, // Publishers are sendonly
|
|
stream: document.getElementById('mypdfview').captureStream(),
|
|
success: this.createStreamSuccess,
|
|
error: error => {
|
|
console.log(error)
|
|
alert(error)
|
|
}
|
|
})
|
|
},
|
|
pdfTimer () {
|
|
// pdf canvas update hack
|
|
var canvas = document.getElementById('mypdfview');
|
|
var context = canvas.getContext('2d');
|
|
var text = '.';
|
|
|
|
context.font = '25px Arial';
|
|
|
|
context.fillStyle = '0,0,0';
|
|
|
|
var x = 0;
|
|
|
|
var y = 0;
|
|
|
|
context.fillText(text, x, y);
|
|
},
|
|
nextPage () {
|
|
this.pageNumber++
|
|
this.renderPage(this.pageNumber)
|
|
|
|
},
|
|
prevPage () {
|
|
this.pageNumber--
|
|
this.renderPage(this.pageNumber)
|
|
|
|
},
|
|
onlocalstream (stream) {
|
|
// Janus.attachMediaStream($('#myvideo').get(0), stream);
|
|
console.log('pdf --------- onlocalstream')
|
|
console.log('pdf --------- onlocalstream')
|
|
console.log('pdf --------- onlocalstream')
|
|
console.log('pdf --------- onlocalstream')
|
|
console.log('pdf --------- onlocalstream')
|
|
this.streamerScreenShare(stream)
|
|
console.log(stream)
|
|
|
|
},
|
|
|
|
async loadFile() {
|
|
|
|
console.log(this.$refs.file.files)
|
|
var file = document.querySelector('#myfile').files[0]
|
|
var pdfdata = await toBase64(file)
|
|
console.log(pdfdata.split('data:application/pdf;base64,')[1])
|
|
|
|
var loadingTask = pdfjsLib.getDocument({data: atob(pdfdata.split('data:application/pdf;base64,')[1])});
|
|
loadingTask.promise.then(pdf => {
|
|
console.log(pdf)
|
|
// var pageNumber = 1;
|
|
this.pdf = pdf
|
|
this.loading = true
|
|
setInterval(this.pdfTimer, 1000/15)
|
|
this.renderPage(1)
|
|
|
|
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
|
|
</style>
|
|
|