最近业务要做一个桌面应用,用于公司内部的直播培训,基础架构采用electron+vue然后接腾讯云的实时音视频和im的sdk来实现。
首先vue创建项目,进入项目后执行vue add electron-builder
来添加electron
和配置启动打包命令,执行完后会生成background.js
,里面是配置的桌面窗口。
async function createWindow() {
win = new BrowserWindow({
width: 770,
height: 450,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
preload: path.join(__dirname, "./preload.js"),
webSecurity: false,
},
// frame: false /* 去掉顶部导航 去掉关闭按钮 最大化最小化按钮 */,
})
if (process.env.WEBPACK_DEV_SERVER_URL) {
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
// win.loadURL("app://./index.html")
win.loadFile("app://./index.html")
}
// win.setMenu(null) // 设置窗口是否可以由用户手动最大化。双击全屏
win.setMaximizable(false)
win.loadFile("./dist/index.html")
}
上面是配置窗口的基本信息,包括窗口大小,配置项之类的。
接下来就是引入官方的插件tim-js-sdk``trtc-electron-sdk``trtc-js-sdk
三个插件,分别是实现im和trtc的插件。
首先说实时音视频,在需要使用音视频的地方初始化:
let videoContainer = document.querySelector("#video-container");
首先获取展示视频流的元素,
let trtcCloud = new TRTCCloud();
然后实例化一个 trtc-electron-sdk,在这里有一个非常主要的参数,是在腾讯音视频官网申请的签名,这里我就放张图展示,SDKAPPID
和SECRETKEY
接下来配置基本的事件订阅,例如进入房间,离开房间等
trtcCloud.on("onError", (errcode, errmsg) => {
console.info("trtc_demo: onError :" + errcode + " msg" + errmsg);
});
trtcCloud.on("onStatistics", (statis) => {
// logger.log("onStatistics", statis);
});
trtcCloud.on("onEnterRoom",
this.onEnterRoom.bind(this)
);
trtcCloud.on("onExitRoom", this.onExitRoom.bind(this));
trtcCloud.on("onUserVideoAvailable", this.onUserVideoAvailable.bind(this));
trtcCloud.on("onRemoteUserEnterRoom", // this.onRemoteUserEnterRoom.bind(this)
(uid) => {
console.log("有用户进入直播间uid:", uid);
}
);
trtcCloud.on("onNetworkQuality", (
localQuality, remoteQulity) => {
// console.log("localQuality.quality", localQuality.quality);
});
trtcCloud.on("onRemoteUserLeaveRoom",this.onRemoteUserLeaveRoom.bind(this));
trtcCloud.on("onUserSubStreamAvailable",this.onUserSubStreamAvailable.bind(this));
接下来就是配置编码参数,TRTCVideoEncParam 的详细说明,请参考:trtc-1252463788.file.myqcloud.com/electron_sd…
然后就是进入房间的参数,TRTCParams 详细说明,请查看文档:trtc-1252463788.file.myqcloud.com/electron_sd…
let param = new TRTCParams();
房间参数根据官方文档必填项进行配置就可以了。
相关文档可到官网观看 cloud.tencent.com/document/pr…
接下来就是im聊天的功能:
tim = TIM.create({
SDKAppID: genTestUserSig("").SDKAppID,
});
let onIMReady = function (event) {
console.log("TIMready");
};
// 监听初始化成功事件tim.on(TIM.EVENT.SDK_READY, onIMReady);
其中SDKAppID
和音视频一样,是在im官网申请的
初始化成功之后,需要进行登录和创建群组才能进行聊天,说白了就类似微信登录和创建群聊
//登录
tim.login({
userID: "",
userSig: "",
}).then((imResponse) => {
console.log(imResponse.data); // 登录成功
if (imResponse.data.repeatLogin === true) {
// 标识账号已登录,本次登录操作为重复登录
console.log(imResponse.data.errorInfo);
}
});
//创建群组
tim.createGroup({
type: TIM.TYPES.GRP_MEETING,
name: planName,
groupID: roomId.toString(),
}).then(function(imResponse){
// 创建成功
console.log("创建群组成功imResponse.data.groupimResponse.data.group",
imResponse.data.group
); // 创建的群的资料})
.catch(function (imError) {
console.warn("创建群组失败createGroup error:", imError);
})
创建成功开始监听im的消息,其中that.onReceiveMessage
就可以去处理各种接收到的消息。
tim.on(TIM.EVENT.MESSAGE_RECEIVED, that.onReceiveMessage);
发送消息首先需要加入群组,需要在一个群组内,就像音视频需要在同一个房间之内一样。
let promise = tim.joinGroup({
groupID: group,
type: TIM.TYPES.GRP_MEETING,
});
promise.then(function (imResponse) {
switch (imResponse.data.status) {
case TIM.TYPES.JOIN_STATUS_WAIT_APPROVAL:
console.log("等待同意");
break; // 等待管理员同意
case TIM.TYPES.JOIN_STATUS_SUCCESS: // 加群成功
console.log("加入的群组", imResponse.data.group);
// 加入的群组资料
break;
case TIM.TYPES.JOIN_STATUS_ALREADY_IN_GROUP: // 已经在群中
console.log("已经在群中");
break;
default:break;
}}).catch(function (imError) {
console.warn("joinGroup error:", imError);
// 申请加群失败的相关信息
});
加群成功,设置角色之后就可以调用发送消息方法tim.sendMessage(message)
了,但是要注意message
的数据结构。
let message = tim.createTextMessage({
to: this.groupId,
conversationType: TIM.TYPES.CONV_GROUP,
payload: {
text: JSON.stringify(msg_staff),
},
});
接收消息除了基本消息之后,有一种自定义消息,可以自定义消息状态,比如直播间的请离和禁言这种基本操作,就可以使用自定义消息,然后根据消息的状态进行对应的操作。
let atObj = {
at: at * 1,
//1开播 2关播 3暂停 4取消暂停 5禁言 6解除禁言 7踢出 8添加管理员 9删除管理员
10关闭摄像头 11开启摄像头 12全员禁言 13取消全员禁言 14用户进入直播间
15用户离开直播间 16停止共享 17开启共享 18解除请离 20上传文件成功
id: uid,
name: name,
};
let messData = {
action: "301", //301为自定义消息
command: "1",
message: JSON.stringify(atObj),
};
let that = this;
let message = tim.createCustomMessage({
to: this.groupId,
conversationType: TIM.TYPES.CONV_GROUP,
payload: {
data: JSON.stringify(messData), // 用于标识该消息
description: "",
extension: "",
},
});
上面可以看到我们有20钟自定义消息类型,可以进行不同的操作。
上面大约就是trtc和im的基本使用,还有一些别的操作没有加进来,如果各位想使用其他的一些复杂功能请到官网查看。
接下来说一下我打包遇到的一些重大的问题。
首先是electron不支持import的方法(注:可能我没有使用插件,只是当时打包报错),然后所有的import
引入方法都改成require
方式引入。
所以需要进行配置,首先可以创建一个preload.js文件
global.electron = require("electron")
window.ipcRenderer = require("electron").ipcRenderer
window.remote = require("electron").remote
sessionStorage.setItem("ipcRenderer", JSON.stringify(window.ipcRenderer))
window.nodeRequire = require
delete window.require
delete window.exports
delete window.module
document.addEventListener("DOMNodeInserted", function (event) {
// 页面内容加载之前需要引入的一些代码
if (document.head && !document.getElementById("module")) {
var script = document.createElement("script")
script.setAttribute("id", "module")
script.innerHTML ="if (typeof module === 'object') {
window.module = module; module = undefined;
}"document.head.appendChild(script)}
})
document.addEventListener("DOMContentLoaded", function (event) {
// 页面内容加载之后需要引入的一些操作
var script = document.createElement("script")
script.innerHTML = `if (window.module) module = window.module;`
document.body.appendChild(script)
})
还记得我在最开始background.js的截图吗,里面在创建窗口的时候引入了这个js,可以解决import报错的问题。
然后就是打包会说找不到trtc和node,或者trtc初始化失败,当时报错截图找不到了。。。。。。。。
这个问题困扰了我们好几天的时间,最后发现是判断引入的问题,一定要注意一下。
在vue.config.js
的文件里
module.exports = {
publicPath: "./",
configureWebpack: {
devtool: "source-map",
module: {
rules: [{
test: /\.node$/,
loader: "native-ext-loader",
options: {
emit: true,
rewritePath:
param.TRTC_ENV === "production"?
param.TARGET_PLATFORM === "win32"?
"./resources/"
: "../Resources"
: "./node_modules/trtc-electron-sdk/build/Release",
},
}],
},
plugins: [new StringReplaceWebpackPlugin()], },
pluginOptions: {
electronBuilder: {
nodeIntegration: true,
},
}
}
其中module
下面的option
里面,rewritePath
判断了当前环境和电脑的操作系统引入了不同文件夹下面的trtc-electron-sdk
,一定要根据电脑环境来进行修改这里面的配置。
这次第一次参与桌面应用和直播音视频流的开发,让我受益很多。
好了,这就是我这次使用的经验,其余遇到的问题还有很多,但是都是小问题,这里就不一一列举,如果有还有问题的,可以在评论区一起探讨。