live.service.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. import { Injectable } from '@angular/core';
  2. import { Router } from '@angular/router';
  3. import { AlertController } from '@ionic/angular';
  4. import * as Parse from 'parse';
  5. import { AiChatService } from './aichart.service';
  6. import { HttpService } from './http.service';
  7. import { MessageService } from './message.service';
  8. declare const AgoraRTC: any;
  9. import BeautyExtension from 'agora-extension-beauty-effect'; // 引入美颜扩展
  10. @Injectable({
  11. providedIn: 'root',
  12. })
  13. export class LiveService {
  14. isAnchor: boolean = false; //是否是主播
  15. options: {
  16. appid: string;
  17. channel: string;
  18. token: string;
  19. } = {
  20. appid: '',
  21. channel: '',
  22. token: '',
  23. };
  24. localTracks: any = {
  25. audioTrack: null,
  26. videoTrack: null,
  27. };
  28. rid?: string; //房间id(channel)
  29. profile?: any = localStorage.getItem('profile');
  30. client: any; //客户端
  31. company: string = '';
  32. UID: any;
  33. tools: any = {
  34. audio: false, //是否关闭音频
  35. camera: false, //是否切换摄像头
  36. glorify: false, //是否开启美颜
  37. mute: false, //是否静音
  38. };
  39. user_published_list: Array<any> = []; //已订阅频道用户列表
  40. timer: any; //轮询获取频道token的定时
  41. alert: any; //提示框
  42. media_devices: {
  43. //音视频设备列表
  44. audioDevices: Array<any>;
  45. videoDevices: Array<any>;
  46. } = {
  47. audioDevices: [],
  48. videoDevices: [],
  49. };
  50. currentUsedDevice: { audioDevice: string; videoDevice: string } = {
  51. //当前使用的设备
  52. audioDevice: '',
  53. videoDevice: '',
  54. };
  55. room?: Parse.Object; //直播间
  56. connection_state?: string; //连接状态
  57. // surplusNumber: number = 0; //剩余可通话时长(单位:秒s)
  58. countdown: number = 0; // 新增倒计时变量
  59. timer_countdown: any;
  60. liveLog?: Parse.Object; //直播记录
  61. isBeautyExtensionRegistered: boolean = false; //是否注册美颜扩展
  62. isOpenEvaluate: boolean = false; //是否开启评价
  63. processor: any; //音视频处理
  64. isNotify: boolean = false;//是否通知剩余2分钟警告
  65. constructor(
  66. private http: HttpService,
  67. private router: Router,
  68. private aiServ: AiChatService,
  69. private alertController: AlertController,
  70. private msgSer: MessageService
  71. ) {
  72. this.client?.leave();
  73. this.company = this.aiServ.company;
  74. this.getProfile();
  75. }
  76. async getProfile() {
  77. if (this.profile) return;
  78. let queryProfile = new Parse.Query('Profile');
  79. queryProfile.equalTo('user', Parse.User.current()?.id);
  80. queryProfile.notEqualTo('isDeleted', true);
  81. queryProfile.equalTo('isCross', true);
  82. this.profile = await queryProfile.first();
  83. this.profile?.id &&
  84. localStorage.setItem('profile', JSON.stringify(this.profile.toJSON()));
  85. }
  86. /* 初始化Agora */
  87. initAgora() {
  88. this.tools = {
  89. audio: false, //是否关闭音频
  90. camera: false, //是否切换摄像头
  91. glorify: false, //是否开启美颜
  92. mute: false, //是否静音
  93. };
  94. this.timer && clearTimeout(this.timer);
  95. this.timer_countdown && clearTimeout(this.timer_countdown);
  96. this.timer_countdown = null;
  97. this.isNotify = false;
  98. this.options['token'] = '';
  99. this.options['channel'] = '';
  100. this.user_published_list = [];
  101. this.client?.leave();
  102. this.client = AgoraRTC.createClient({ mode: 'rtc', codec: 'h264' });
  103. // AgoraRTC.enableLogUpload();
  104. AgoraRTC.setLogLevel(4)
  105. if (!this.isBeautyExtensionRegistered) {
  106. // 创建 BeautyExtension 实例
  107. const extension: any = new BeautyExtension();
  108. // 注册插件
  109. AgoraRTC.registerExtensions([extension]);
  110. // 创建 BeautyProcessor 实例
  111. this.processor = extension.createProcessor();
  112. // this.isBeautyExtensionRegistered = true;
  113. }
  114. this.setBeautyOptions();
  115. }
  116. // 获取所有音视频设备
  117. getDevices() {
  118. AgoraRTC.getDevices()
  119. .then((devices: any) => {
  120. this.media_devices.audioDevices = devices.filter(function (
  121. device: any
  122. ) {
  123. return device.kind === 'audioinput';
  124. });
  125. this.media_devices.videoDevices = devices.filter(function (
  126. device: any
  127. ) {
  128. return device.kind === 'videoinput';
  129. });
  130. console.log(this.media_devices);
  131. this.currentUsedDevice = {
  132. audioDevice: this.media_devices.audioDevices[0].deviceId,
  133. videoDevice: this.media_devices.videoDevices[0].deviceId,
  134. };
  135. })
  136. .then((tracks: any) => {
  137. console.log(tracks);
  138. })
  139. .catch((err: any) => {
  140. console.warn('获取媒体权限失败', err);
  141. this.alertTips('获取媒体权限失败');
  142. });
  143. }
  144. /* 获取token */
  145. async getToken(room: Parse.Object) {
  146. this.room = room;
  147. this.isAnchor = room?.get('user')?.id === Parse.User.current()?.id;
  148. this.timer && clearTimeout(this.timer);
  149. let remoteEle = document.getElementById('vice-video');
  150. (remoteEle as any).style.display = 'none';
  151. //获取频道token记录
  152. let baseurl = 'https://server.fmode.cn/api/ailiao/token';
  153. if (this.isAnchor) {
  154. this.UID = 111111;
  155. baseurl = 'https://server.fmode.cn/api/webrtc/build_token';
  156. }
  157. let reqBody = {
  158. company: this.company, // this.aiSer.company,
  159. profile: room?.get('profile').id,
  160. channelName: room?.get('profile').id,
  161. };
  162. let data: any = await this.http.httpRequst(baseurl, reqBody, 'POST');
  163. console.log(data);
  164. if (data.code == 200) {
  165. this.options.token = data.data.token;
  166. this.options.appid = data.data.appid;
  167. } else {
  168. this.timer = setTimeout(() => {
  169. this.getToken(room);
  170. }, 2000);
  171. return;
  172. }
  173. this.options.channel = room?.get('profile').id;
  174. this.join();
  175. }
  176. async updateToken(pid: string) {
  177. let sql = `select "rtc"."objectId" as "rid","rtc"."channel", "rtc"."token", "rtc"."expiraTime" from "RtcToken" as "rtc" where "rtc"."profile" = '${pid}' and "rtc"."expiraTime" >= now() order by "createdAt" desc limit 1`;
  178. let tokenData: any = await this.http.customSQL(sql);
  179. if (
  180. tokenData &&
  181. tokenData.code == 200 &&
  182. tokenData.data &&
  183. tokenData.data.length > 0
  184. ) {
  185. return tokenData.data[0];
  186. } else {
  187. return null;
  188. }
  189. }
  190. /* 进入频道 */
  191. async join() {
  192. let path = location.pathname;
  193. if (path.indexOf('/live/link-room/') == -1) return;
  194. console.log('频道id:', this.options.channel);
  195. this.client
  196. .join(
  197. this.options.appid,
  198. this.options.channel,
  199. this.options.token,
  200. this.UID
  201. )
  202. .then(async (uid: any) => {
  203. // await this.client.setClientRole('host');
  204. this.connection_state = this.client.connectionState;
  205. console.log('进入频道当前uid:', uid, '状态:', this.connection_state);
  206. let user = Parse.User.current();
  207. this.msgSer?.publishMessage(
  208. `${user?.get('nickname')}加入频道直播`,
  209. this.room?.get('user')?.id
  210. );
  211. if (!this.isAnchor) {
  212. // 观众进入直播间,创建直播记录
  213. await this.createLiveLog(uid);
  214. } else {
  215. //主播进入直播间直接发送自己推流
  216. await this.publishSelf();
  217. }
  218. await this.joinReady();
  219. this.afterJoin();
  220. })
  221. .catch((err: any) => {
  222. console.error('进入频道失败:', err);
  223. });
  224. }
  225. /* 发布本地视频 */
  226. async publishSelf() {
  227. try {
  228. let data = await Promise.all([
  229. /* 创建音频和视频轨道 */
  230. AgoraRTC.createMicrophoneAudioTrack(this.currentUsedDevice.audioDevice),
  231. AgoraRTC.createCameraVideoTrack(this.currentUsedDevice.videoDevice),
  232. ]);
  233. this.localTracks.audioTrack = data[0];
  234. this.localTracks.videoTrack = data[1];
  235. // console.log(this.localTracks);
  236. let remoteEle = document.getElementById('vice-video');
  237. if (remoteEle) {
  238. remoteEle.textContent = '';
  239. remoteEle.style.display = 'block';
  240. }
  241. this.localTracks.videoTrack.play('vice-video'); //播放自己视频渲染
  242. // if (this.tools['audio']) {
  243. // this.localTracks.audioTrack.setEnabled(false);
  244. // } else {
  245. // this.localTracks.audioTrack.setEnabled(true);
  246. // }
  247. if (this.processor && this.localTracks.videoTrack) {
  248. // 将插件注入 SDK 内的视频处理管道
  249. this.localTracks.videoTrack
  250. .pipe(this.processor)
  251. .pipe(this.localTracks.videoTrack.processorDestination);
  252. // 开启美颜
  253. await this.processor.enable();
  254. }
  255. await this.client.publish(Object.values(this.localTracks));
  256. } catch (err) {
  257. console.log('发布本地视频失败:', err);
  258. // history.back()
  259. this.alertTips('发布本地视频失败,请检查摄像头是否授权或正常', '提示');
  260. await this.client.leave();
  261. }
  262. }
  263. /* 设置各项美颜参数 */
  264. async setBeautyOptions() {
  265. this.processor.setOptions({
  266. lighteningContrastLevel: 2, // 对比度
  267. lighteningLevel: 0.8, // 亮度
  268. smoothnessLevel: 0.8, // 平滑度
  269. sharpnessLevel: 0.5, // 锐化程度
  270. rednessLevel: 0.5, // 红润度
  271. });
  272. this.tools['glorify'] = true;
  273. }
  274. /* 订阅远程视频 */
  275. async joinReady() {
  276. this.client.remoteUsers.forEach((user: any) => {
  277. // console.log('remoteUsers', user.uid);
  278. this.client.subscribe(user, 'audio').then((audioTrack: any) => {
  279. if (!this.user_published_list.find((item) => item.uid === user.uid)) {
  280. this.user_published_list.push(user);
  281. }
  282. audioTrack.setVolume(100);
  283. audioTrack.play();
  284. });
  285. this.client.subscribe(user, 'video').then((videoTrack: any) => {
  286. let remoteEle = document.getElementById('video');
  287. if (remoteEle) {
  288. remoteEle.textContent = '';
  289. }
  290. videoTrack.play('video');
  291. });
  292. });
  293. this.client.on('user-joined', (user: any) => {
  294. console.log(user, `${user.uid} 加入频道`);
  295. });
  296. this.client.on('user-published', async (user: any, mediaType: string) => {
  297. console.log('用户推流成功', user);
  298. await this.client.subscribe(user, mediaType);
  299. let remoteEle = document.getElementById('video');
  300. if (remoteEle) {
  301. remoteEle.textContent = '';
  302. }
  303. if (mediaType === 'video') {
  304. user.videoTrack.play('video');
  305. this.alert?.dismiss();
  306. }
  307. if (mediaType === 'audio') {
  308. user.audioTrack.play();
  309. if (!this.user_published_list.find((item) => item.uid === user.uid)) {
  310. this.user_published_list.push(user);
  311. }
  312. }
  313. });
  314. this.client.on('user-unpublished', async (user: any, mediaType: string) => {
  315. if (mediaType === 'audio') {
  316. console.log('对方已静音');
  317. let idx = this.user_published_list.findIndex(
  318. (item) => item.uid === user.uid
  319. );
  320. if (idx >= 0) {
  321. this.user_published_list.splice(idx, 1);
  322. }
  323. }
  324. if (mediaType === 'video') {
  325. console.log('用户取消推流');
  326. // let remoteEle = document.getElementById('video');
  327. // if (remoteEle) {
  328. // remoteEle.textContent = '对方已离开直播间';
  329. // }
  330. // // this.client.leave();
  331. // this.alertTips('对方已离开直播间');
  332. }
  333. });
  334. // 注册用户离开事件处理函数
  335. this.client.on('user-left', (user: any) => {
  336. console.log(`用户 ${user.uid} 离开了频道`);
  337. //主播离开,停止计时计费
  338. if (user.uid !== 100001) {
  339. this.client.leave();
  340. this.alertTips('对方已离开直播间');
  341. }
  342. });
  343. this.client.on(
  344. 'connection-state-change',
  345. (curState: any, prevState: any) => {
  346. this.connection_state = curState;
  347. if (
  348. curState == 'RECONNECTING' ||
  349. curState == 'DISCONNECTED' ||
  350. curState == 'DISCONNECTING'
  351. ) {
  352. this.timer && clearTimeout(this.timer);
  353. this.timer_countdown && clearTimeout(this.timer_countdown);
  354. if (!this.isAnchor) {
  355. //用户离开直播间,断开与主播状态连接频道
  356. this.msgSer.unsubscribeMessage(this.room?.get('user')?.id);
  357. this.isOpenEvaluate = true;
  358. }
  359. console.log(this.router.url);
  360. if (
  361. this.router.url.indexOf('/live/link-room/') == 0 &&
  362. curState == 'DISCONNECTED'
  363. ) {
  364. localStorage.removeItem('isLive');
  365. history.back();
  366. }
  367. }
  368. console.log('live状态变更:', this.connection_state);
  369. }
  370. );
  371. this.monitorDevices();
  372. }
  373. async createLiveLog(uid: string) {
  374. let profile = JSON.parse(localStorage.getItem('profile') || '{}');
  375. let obj = Parse.Object.extend('LiveLog');
  376. let liveLog = new obj();
  377. liveLog.set('title', `与${Parse.User.current()?.get('nickname')}进行直播`);
  378. liveLog.set('uid', String(uid));
  379. liveLog.set('company', {
  380. __type: 'Pointer',
  381. className: 'Company',
  382. objectId: this.company,
  383. });
  384. liveLog.set('room', {
  385. __type: 'Pointer',
  386. className: 'Room',
  387. objectId: this.room?.id,
  388. });
  389. liveLog.set('user', {
  390. __type: 'Pointer',
  391. className: '_User',
  392. objectId: Parse.User.current()?.id,
  393. });
  394. liveLog.set('profile', {
  395. __type: 'Pointer',
  396. className: 'Profile',
  397. objectId: this.room?.get('profile')?.id,
  398. });
  399. this.liveLog = await liveLog.save();
  400. }
  401. /* 连线成功立即创建直播记录,同步获取剩余可通话时长,并且开始计时 */
  402. async afterJoin() {
  403. this.timer && clearTimeout(this.timer);
  404. this.timer_countdown && clearTimeout(this.timer_countdown);
  405. const targetUser = this.client.remoteUsers?.find(
  406. (user: any) => user.uid !== 100001
  407. ); //排出超管
  408. console.log(targetUser);
  409. if (this.client.remoteUsers.length > 0 && targetUser) {
  410. if (this.isAnchor) {
  411. //如果是主播,进入获取remoteUsers.user获取livelog再获取对方剩余通话时长
  412. this.getLiveLog(targetUser.uid);
  413. } else {
  414. let query = new Parse.Query('LiveLog');
  415. query.equalTo('objectId', this.liveLog?.id);
  416. query.equalTo('isLive', true);
  417. query.select('objectId');
  418. const resultData = await query.first();
  419. if (resultData?.id) {
  420. //首次进入至少计时2分钟,不足2分钟按2分钟计算扣时
  421. await this.publishSelf();
  422. await this.get_duration();
  423. this.computeDuration(60000 * 2);
  424. } else {
  425. this.timer = setTimeout(() => {
  426. this.afterJoin();
  427. }, 1000);
  428. }
  429. }
  430. } else {
  431. this.timer = setTimeout(() => {
  432. this.afterJoin();
  433. }, 1000);
  434. }
  435. }
  436. async getLiveLog(tarUid: string) {
  437. // let uid = this.client.remoteUsers[0].uid;
  438. this.timer && clearTimeout(this.timer);
  439. let query = new Parse.Query('LiveLog');
  440. query.equalTo('uid', String(tarUid));
  441. query.equalTo('room', this.room?.id);
  442. query.notEqualTo('isDeleted', true);
  443. query.notEqualTo('isLive', true);
  444. query.descending('createdAt');
  445. this.liveLog = await query.first();
  446. if (this.liveLog?.id) {
  447. this.liveLog?.set('isLive', true);
  448. await this.liveLog?.save();
  449. await this.get_duration();
  450. this.getCallDuration();
  451. return;
  452. }
  453. this.timer = setTimeout(() => {
  454. this.getLiveLog(tarUid);
  455. }, 1000);
  456. }
  457. async get_duration() {
  458. // this.timer_countdown && clearTimeout(this.timer_countdown);
  459. let url = 'https://server.fmode.cn/api/ailiao/remain_second';
  460. let params = {
  461. rid: this.room?.id,
  462. uid: this.liveLog?.get('user')?.id || this.liveLog?.get('user')?.objectId,
  463. };
  464. let data = await this.http.httpRequst(url, params, 'POST');
  465. console.log(data);
  466. this.countdown = data.data ?? 0;
  467. // this.countdown = this.surplusNumber; // 初始化倒计时
  468. let arr = ['CONNECTING', 'CONNECTED'];
  469. if (arr.includes(this.connection_state as any)) {
  470. if (this.countdown <= 120 && !this.isNotify) {
  471. this.alertTips('剩余通话时间不足2分钟,请及时充值');
  472. this.isNotify = true;
  473. }
  474. !this.timer_countdown && this.startCountdown();
  475. }
  476. }
  477. startCountdown() {
  478. this.timer_countdown && clearTimeout(this.timer_countdown);
  479. this.timer_countdown = setTimeout(() => {
  480. if (this.countdown > 0) {
  481. this.countdown--;
  482. console.log(this.countdown);
  483. this.startCountdown();
  484. return;
  485. }
  486. clearTimeout(this.timer_countdown);
  487. // history.back()
  488. this.alertTips('通话时间结束');
  489. this.client.leave(); // 结束通话
  490. }, 1000);
  491. }
  492. /* 开始计时 */
  493. async computeDuration(num?: number) {
  494. //每10秒保存一次数据
  495. this.timer && clearTimeout(this.timer);
  496. let arr = ['CONNECTING', 'CONNECTED'];
  497. if (
  498. !arr.includes(this.connection_state as any) ||
  499. this.router.url.indexOf('/live/link-room/') == -1
  500. ) {
  501. return;
  502. }
  503. let p = JSON.parse(this.profile);
  504. // console.log(p);
  505. let url = 'https://server.fmode.cn/api/ailiao/count/duration';
  506. let params = {
  507. company: this.company,
  508. profile: p?.objectId,
  509. rid: this.room?.id,
  510. uid: Parse.User.current()?.id,
  511. duration: num ? num / 1000 : 10,
  512. logid: this.liveLog?.id,
  513. };
  514. let data = await this.http.httpRequst(url, params, 'POST');
  515. // console.log(data);
  516. this.timer = setTimeout(() => {
  517. this.computeDuration();
  518. }, num ?? 10000);
  519. }
  520. /* 主播每10s获取一次对方可通话时长 */
  521. getCallDuration() {
  522. this.timer && clearTimeout(this.timer);
  523. this.timer = setTimeout(async () => {
  524. await this.get_duration();
  525. let arr = ['CONNECTING', 'CONNECTED'];
  526. if (arr.includes(this.connection_state as any)) {
  527. this.getCallDuration();
  528. }
  529. }, 10000);
  530. }
  531. /* 监听音视频设备插拔 */
  532. monitorDevices() {
  533. AgoraRTC.onMicrophoneChanged = async (changedDevice: any) => {
  534. // 插入麦克风设备时,切换到新插入的设备
  535. if (changedDevice.state === 'ACTIVE') {
  536. this.localTracks.audioTrack.setDevice(changedDevice.device.deviceId);
  537. this.currentUsedDevice.audioDevice = changedDevice.device.deviceId;
  538. // 拔出设备为当前设备时,切换到一个已有的设备
  539. } else if (
  540. changedDevice.device.label ===
  541. this.localTracks.audioTrack.getTrackLabel()
  542. ) {
  543. const oldMicrophones = await AgoraRTC.getMicrophones();
  544. oldMicrophones[0] &&
  545. this.localTracks.audioTrack.setDevice(oldMicrophones[0].deviceId);
  546. this.currentUsedDevice.audioDevice = oldMicrophones[0].deviceId;
  547. }
  548. };
  549. AgoraRTC.onCameraChanged = async (changedDevice: any) => {
  550. // 插入相机设备时,切换到新插入的设备
  551. if (changedDevice.state === 'ACTIVE') {
  552. this.localTracks.videoTrack.setDevice(changedDevice.device.deviceId);
  553. this.currentUsedDevice.videoDevice = changedDevice.device.deviceId;
  554. // 拔出设备为当前设备时,切换到一个已有的设备
  555. } else if (
  556. changedDevice.device.label ===
  557. this.localTracks.videoTrack.getTrackLabel()
  558. ) {
  559. const oldCameras = await AgoraRTC.getCameras();
  560. oldCameras[0] &&
  561. this.localTracks.videoTrack.setDevice(oldCameras[0].deviceId);
  562. this.currentUsedDevice.videoDevice = oldCameras[0].deviceId;
  563. }
  564. };
  565. }
  566. /* 关开麦 */
  567. async updatePublishedAudioTrack() {
  568. this.tools['audio'] = !this.tools['audio'];
  569. if (this.tools['audio'] && this.localTracks.audioTrack) {
  570. // await this.localTracks.audioTrack.setEnabled(false);
  571. this.localTracks.audioTrack.setVolume(0);
  572. console.log('停止推送音频');
  573. } else {
  574. // await this.localTracks.audioTrack.setEnabled(true);
  575. this.localTracks.audioTrack.setVolume(100);
  576. console.log('恢复推送音频');
  577. }
  578. // await this.client.unpublish(this.localTracks.audioTrack);
  579. return true;
  580. }
  581. /* 静音 */
  582. async muteAudio() {
  583. this.tools['mute'] = !this.tools['mute'];
  584. let list = Array.from(this.user_published_list);
  585. for (let index = 0; index < list.length; index++) {
  586. const user = list[index];
  587. if (this.tools['mute']) {
  588. console.log('静音');
  589. await this.client.unsubscribe(user, 'audio');
  590. } else {
  591. await this.client.subscribe(user, 'audio').then((audioTrack: any) => {
  592. audioTrack.setVolume(100);
  593. audioTrack.play();
  594. });
  595. console.log('恢复声音');
  596. }
  597. }
  598. }
  599. /* 切换摄像头 */
  600. async changeCamera() {
  601. const oldCameras = await AgoraRTC.getCameras(true);
  602. // console.log('oldCameras:', oldCameras);
  603. let newCamers = oldCameras.find(
  604. (item: any) => item.deviceId !== this.currentUsedDevice.videoDevice
  605. );
  606. console.log(newCamers);
  607. newCamers &&
  608. this.localTracks.videoTrack
  609. .setDevice(newCamers.deviceId)
  610. .then(() => {
  611. this.tools['camera'] = !this.tools['camera'];
  612. this.currentUsedDevice.videoDevice = newCamers.deviceId;
  613. })
  614. .catch((err: any) => {
  615. console.log('set device error', err);
  616. this.tools['camera'] = !this.tools['camera'];
  617. this.currentUsedDevice.videoDevice = newCamers.deviceId;
  618. // this.alertTips('切换摄像头失败');
  619. });
  620. // await this.localTracks.videoTrack.setDevice({facingMode: this.tools['camera'] ? 'user' : 'environment'})
  621. // this.tools['camera'] = !this.tools['camera'];
  622. // this.currentUsedDevice.videoDevice = newCamers.deviceId;
  623. return true;
  624. }
  625. /* 切换美颜 */
  626. changeBeauty() {
  627. if (!this.tools['glorify']) {
  628. this.setBeautyOptions();
  629. } else {
  630. // 关闭美颜
  631. this.processor.setOptions({
  632. lighteningContrastLevel: 0,
  633. lighteningLevel: 0,
  634. smoothnessLevel: 0,
  635. sharpnessLevel: 0,
  636. rednessLevel: 0,
  637. });
  638. this.tools['glorify'] = false;
  639. }
  640. }
  641. /* 提示 */
  642. async alertTips(message: string, title?: string, callBack?: Function) {
  643. this.alert = await this.alertController.create({
  644. header: title || '提示',
  645. message: message,
  646. backdropDismiss: false,
  647. buttons: [
  648. {
  649. text: '确认',
  650. handler: () => {
  651. callBack && callBack();
  652. },
  653. },
  654. ],
  655. });
  656. await this.alert.present();
  657. }
  658. }