[*] 共享本地视频文件
This commit is contained in:
@@ -887,23 +887,19 @@ class Taoyao {
|
|||||||
});
|
});
|
||||||
producer.observer.on("resume", () => {
|
producer.observer.on("resume", () => {
|
||||||
console.debug("生产者恢复", producer.id, streamId);
|
console.debug("生产者恢复", producer.id, streamId);
|
||||||
me.push(
|
me.push(protocol.buildMessage("media::producer::resume", {
|
||||||
protocol.buildMessage("media::producer::resume", {
|
roomId,
|
||||||
roomId : roomId,
|
producerId: producer.id
|
||||||
producerId: producer.id
|
}));
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
// producer.observer.on("score", fn(score));
|
// producer.observer.on("score", fn(score));
|
||||||
producer.on("score", (score) => {
|
producer.on("score", (score) => {
|
||||||
console.debug("生产者评分", producer.id, streamId, score);
|
console.debug("生产者评分", producer.id, streamId, score);
|
||||||
me.push(
|
me.push(protocol.buildMessage("media::producer::score", {
|
||||||
protocol.buildMessage("media::producer::score", {
|
score,
|
||||||
roomId : roomId,
|
roomId,
|
||||||
producerId: producer.id,
|
producerId: producer.id,
|
||||||
score : score,
|
}));
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
// producer.observer.on("videoorientationchange", fn(videoOrientation));
|
// producer.observer.on("videoorientationchange", fn(videoOrientation));
|
||||||
producer.on("videoorientationchange", (videoOrientation) => {
|
producer.on("videoorientationchange", (videoOrientation) => {
|
||||||
@@ -926,13 +922,6 @@ class Taoyao {
|
|||||||
producerId: producer.id
|
producerId: producer.id
|
||||||
};
|
};
|
||||||
me.push(message);
|
me.push(message);
|
||||||
// me.push(
|
|
||||||
// protocol.buildMessage("media::producer::score", {
|
|
||||||
// roomId : roomId,
|
|
||||||
// producerId: producer.id,
|
|
||||||
// score : producer.score,
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
if (producer.kind === "audio") {
|
if (producer.kind === "audio") {
|
||||||
// TODO:关闭生产者时移除监听
|
// TODO:关闭生产者时移除监听
|
||||||
room.audioLevelObserver
|
room.audioLevelObserver
|
||||||
@@ -1161,13 +1150,6 @@ class Taoyao {
|
|||||||
);
|
);
|
||||||
await consumer.resume();
|
await consumer.resume();
|
||||||
consumer.localPaused = false;
|
consumer.localPaused = false;
|
||||||
// me.push(
|
|
||||||
// protocol.buildMessage("media::consumer::score", {
|
|
||||||
// roomId : roomId,
|
|
||||||
// consumerId: consumer.id,
|
|
||||||
// score : consumer.score,
|
|
||||||
// })
|
|
||||||
// );
|
|
||||||
})()
|
})()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -550,6 +550,8 @@ class Taoyao extends RemoteClient {
|
|||||||
mediasoupDevice;
|
mediasoupDevice;
|
||||||
// 文件共享
|
// 文件共享
|
||||||
fileVideo;
|
fileVideo;
|
||||||
|
// 文件共享地址
|
||||||
|
fileVideoObjectURL;
|
||||||
// 视频来源:file|camera|screen
|
// 视频来源:file|camera|screen
|
||||||
videoSource;
|
videoSource;
|
||||||
// 强制使用TCP
|
// 强制使用TCP
|
||||||
@@ -608,7 +610,6 @@ class Taoyao extends RemoteClient {
|
|||||||
dataProduce = true,
|
dataProduce = true,
|
||||||
audioProduce = true,
|
audioProduce = true,
|
||||||
videoProduce = true,
|
videoProduce = true,
|
||||||
fileVideo = null,
|
|
||||||
videoSource = "camera",
|
videoSource = "camera",
|
||||||
forceTcp = false,
|
forceTcp = false,
|
||||||
forceVP8 = false,
|
forceVP8 = false,
|
||||||
@@ -631,7 +632,6 @@ class Taoyao extends RemoteClient {
|
|||||||
this.dataProduce = dataProduce;
|
this.dataProduce = dataProduce;
|
||||||
this.audioProduce = audioProduce;
|
this.audioProduce = audioProduce;
|
||||||
this.videoProduce = videoProduce;
|
this.videoProduce = videoProduce;
|
||||||
this.fileVideo = fileVideo;
|
|
||||||
this.videoSource = videoSource;
|
this.videoSource = videoSource;
|
||||||
this.forceTcp = forceTcp;
|
this.forceTcp = forceTcp;
|
||||||
this.forceVP8 = forceVP8;
|
this.forceVP8 = forceVP8;
|
||||||
@@ -930,6 +930,52 @@ class Taoyao extends RemoteClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择视频文件
|
||||||
|
*/
|
||||||
|
async getFileVideo() {
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "file";
|
||||||
|
const select = new Promise((resolve, reject) => {
|
||||||
|
input.onchange = (e) => {
|
||||||
|
resolve(input.value);
|
||||||
|
}
|
||||||
|
input.oncancel = (e) => {
|
||||||
|
resolve(null);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
input.click();
|
||||||
|
const file = await select;
|
||||||
|
input.remove();
|
||||||
|
if(!file) {
|
||||||
|
console.debug("没有选择共享文件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.debug("选择文件", file);
|
||||||
|
this.fileVideo = document.createElement("video");
|
||||||
|
this.fileVideo.loop = true;
|
||||||
|
this.fileVideo.muted = true;
|
||||||
|
this.fileVideo.controls = true;
|
||||||
|
this.fileVideo.src = URL.createObjectURL(input.files[0]);
|
||||||
|
this.fileVideo.style = "position:fixed;top:1rem;left:1rem;width:128px;border:2px solid #FFF;";
|
||||||
|
// this.fileVideo.style.display = "none";
|
||||||
|
document.body.appendChild(this.fileVideo);
|
||||||
|
// 开始播放不然不能采集
|
||||||
|
await this.fileVideo.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放视频文件
|
||||||
|
*/
|
||||||
|
async closeFileVideo() {
|
||||||
|
if(this.fileVideo) {
|
||||||
|
this.fileVideo.remove();
|
||||||
|
}
|
||||||
|
if(this.fileVideoObjectURL) {
|
||||||
|
URL.revokeObjectURL(this.fileVideoObjectURL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns 媒体
|
* @returns 媒体
|
||||||
*/
|
*/
|
||||||
@@ -937,6 +983,7 @@ class Taoyao extends RemoteClient {
|
|||||||
const me = this;
|
const me = this;
|
||||||
let stream;
|
let stream;
|
||||||
if (me.videoSource === "file") {
|
if (me.videoSource === "file") {
|
||||||
|
await this.getFileVideo();
|
||||||
stream = me.fileVideo.captureStream();
|
stream = me.fileVideo.captureStream();
|
||||||
} else if (me.videoSource === "camera") {
|
} else if (me.videoSource === "camera") {
|
||||||
console.debug("媒体配置", me.audioConfig, me.videoConfig);
|
console.debug("媒体配置", me.audioConfig, me.videoConfig);
|
||||||
@@ -1016,6 +1063,7 @@ class Taoyao extends RemoteClient {
|
|||||||
let stream;
|
let stream;
|
||||||
const me = this;
|
const me = this;
|
||||||
if (me.videoSource === "file") {
|
if (me.videoSource === "file") {
|
||||||
|
await this.getFileVideo();
|
||||||
stream = me.fileVideo.captureStream();
|
stream = me.fileVideo.captureStream();
|
||||||
} else if (me.videoSource === "camera") {
|
} else if (me.videoSource === "camera") {
|
||||||
stream = await navigator.mediaDevices.getUserMedia({
|
stream = await navigator.mediaDevices.getUserMedia({
|
||||||
@@ -1854,57 +1902,6 @@ class Taoyao extends RemoteClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 恢复生产者信令
|
|
||||||
*
|
|
||||||
* @param {*} producerId 生产者ID
|
|
||||||
*/
|
|
||||||
mediaProducerResume(producerId) {
|
|
||||||
const me = this;
|
|
||||||
const producer = me.getProducer(producerId);
|
|
||||||
if(producer) {
|
|
||||||
if(!producer.paused) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.debug("恢复生产者", producerId);
|
|
||||||
me.push(protocol.buildMessage("media::producer::resume", {
|
|
||||||
roomId : me.roomId,
|
|
||||||
producerId: producerId,
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
console.debug("恢复生产者无效", producerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 恢复生产者信令
|
|
||||||
*
|
|
||||||
* @param {*} message 信令消息
|
|
||||||
*/
|
|
||||||
async defaultMediaProducerResume(message) {
|
|
||||||
const me = this;
|
|
||||||
const {
|
|
||||||
roomId,
|
|
||||||
producerId
|
|
||||||
} = message.body;
|
|
||||||
const producer = me.getProducer(producerId);
|
|
||||||
if (producer) {
|
|
||||||
console.debug("恢复生产者", producerId);
|
|
||||||
producer.resume();
|
|
||||||
} else {
|
|
||||||
console.debug("恢复生产者无效", producerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 媒体生产者评分信令
|
|
||||||
*
|
|
||||||
* @param {*} message 信令消息
|
|
||||||
*/
|
|
||||||
defaultMediaProducerScore(message) {
|
|
||||||
console.debug("生产者评分", message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 消费媒体信令
|
* 消费媒体信令
|
||||||
*
|
*
|
||||||
@@ -2396,6 +2393,7 @@ class Taoyao extends RemoteClient {
|
|||||||
async exchangeVideoSource(videoSource) {
|
async exchangeVideoSource(videoSource) {
|
||||||
const me = this;
|
const me = this;
|
||||||
console.debug("切换视频来源", videoSource, me.videoSource);
|
console.debug("切换视频来源", videoSource, me.videoSource);
|
||||||
|
const old = this.videoSource;
|
||||||
if(videoSource) {
|
if(videoSource) {
|
||||||
me.videoSource = videoSource;
|
me.videoSource = videoSource;
|
||||||
} else {
|
} else {
|
||||||
@@ -2410,6 +2408,9 @@ class Taoyao extends RemoteClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await me.updateVideoProducer();
|
await me.updateVideoProducer();
|
||||||
|
if(old === "file") {
|
||||||
|
this.closeFileVideo();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2468,6 +2469,59 @@ class Taoyao extends RemoteClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复生产者信令
|
||||||
|
*
|
||||||
|
* @param {*} producerId 生产者ID
|
||||||
|
*/
|
||||||
|
mediaProducerResume(producerId) {
|
||||||
|
const producer = this.getProducer(producerId);
|
||||||
|
if(!producer) {
|
||||||
|
console.debug("恢复生产者(生产者无效)", producerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!producer.paused) {
|
||||||
|
console.debug("恢复生产者(生产者已经恢复)", producerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.debug("恢复生产者", producerId);
|
||||||
|
this.push(protocol.buildMessage("media::producer::resume", {
|
||||||
|
producerId,
|
||||||
|
roomId: this.roomId,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复生产者信令
|
||||||
|
*
|
||||||
|
* @param {*} message 信令消息
|
||||||
|
*/
|
||||||
|
async defaultMediaProducerResume(message) {
|
||||||
|
const {
|
||||||
|
producerId
|
||||||
|
} = message.body;
|
||||||
|
const producer = this.getProducer(producerId);
|
||||||
|
if (!producer) {
|
||||||
|
console.debug("恢复生产者(生产者无效)", producerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!producer.paused) {
|
||||||
|
console.debug("恢复生产者(生产者已经恢复)", producerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.debug("恢复生产者", producerId);
|
||||||
|
producer.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 媒体生产者评分信令
|
||||||
|
*
|
||||||
|
* @param {*} message 信令消息
|
||||||
|
*/
|
||||||
|
defaultMediaProducerScore(message) {
|
||||||
|
console.debug("生产者评分", message);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询生产者状态信令
|
* 查询生产者状态信令
|
||||||
*
|
*
|
||||||
@@ -3417,19 +3471,20 @@ class Taoyao extends RemoteClient {
|
|||||||
* @param {*} video 视频
|
* @param {*} video 视频
|
||||||
*/
|
*/
|
||||||
localPhotograph(video) {
|
localPhotograph(video) {
|
||||||
const me = this;
|
const canvas = document.createElement("canvas");
|
||||||
const canvas = document.createElement('canvas');
|
|
||||||
canvas.width = video.videoWidth;
|
canvas.width = video.videoWidth;
|
||||||
canvas.height = video.videoHeight;
|
canvas.height = video.videoHeight;
|
||||||
const context = canvas.getContext('2d');
|
const context = canvas.getContext("2d");
|
||||||
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
|
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
|
||||||
const dataURL = canvas.toDataURL('images/png');
|
const dataURL = canvas.toDataURL("images/png");
|
||||||
const download = document.createElement('a');
|
const download = document.createElement("a");
|
||||||
download.href = dataURL;
|
download.href = dataURL;
|
||||||
download.download = 'taoyao.png';
|
download.download = "taoyao.png";
|
||||||
download.style.display = 'none';
|
// download.style.display = "none";
|
||||||
document.body.appendChild(download);
|
// document.body.appendChild(download);
|
||||||
download.click();
|
download.click();
|
||||||
|
// 释放资源
|
||||||
|
canvas.remove();
|
||||||
download.remove();
|
download.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3485,11 +3540,11 @@ class Taoyao extends RemoteClient {
|
|||||||
me.mediaRecorder.onstop = (e) => {
|
me.mediaRecorder.onstop = (e) => {
|
||||||
const blob = new Blob(me.mediaRecorderChunks);
|
const blob = new Blob(me.mediaRecorderChunks);
|
||||||
const objectURL = URL.createObjectURL(blob);
|
const objectURL = URL.createObjectURL(blob);
|
||||||
const download = document.createElement('a');
|
const download = document.createElement("a");
|
||||||
download.href = objectURL;
|
download.href = objectURL;
|
||||||
download.download = 'taoyao.mp4';
|
download.download = "taoyao.mp4";
|
||||||
download.style.display = 'none';
|
// download.style.display = "none";
|
||||||
document.body.appendChild(download);
|
// document.body.appendChild(download);
|
||||||
download.click();
|
download.click();
|
||||||
download.remove();
|
download.remove();
|
||||||
URL.revokeObjectURL(objectURL);
|
URL.revokeObjectURL(objectURL);
|
||||||
|
|||||||
Reference in New Issue
Block a user