scene.service.ts 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441
  1. import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
  2. import { ClientGrpc, Client } from '@nestjs/microservices';
  3. import { grpcClientOptions } from './grpc-scene.options';
  4. import { Logger } from '@nestjs/common';
  5. import { DataChannel, PeerConnection } from 'node-datachannel';
  6. import { BehaviorSubject } from 'rxjs';
  7. // import * as streamBuffers from 'stream-buffers';
  8. import { ActionType } from './actionType';
  9. import { CacheService } from 'src/cache/cache.service';
  10. import { StreamService } from './stream/stream.service';
  11. // import { InjectQueue } from '@nestjs/bull';
  12. // import { Queue } from 'bull';
  13. import { RotateService } from 'src/rotate/rotate.service';
  14. // import { DelayQueue, RxQueue, DebounceQueue } from 'rx-queue';
  15. import { DelayQueue, RxQueue, DebounceQueue } from '../queue/mod';
  16. import { MoveService } from 'src/move/move.service';
  17. import { GetRouterService } from 'src/get-router/get-router.service';
  18. import { ConfigService } from '@nestjs/config';
  19. const seqExeAsyncFn = (asyncFn) => {
  20. let runPromise = null;
  21. return function seq(...args) {
  22. if (!runPromise) {
  23. runPromise = asyncFn.apply(this, args);
  24. runPromise.then(() => (runPromise = null));
  25. return runPromise;
  26. } else {
  27. return runPromise.then(() => seq.apply(this, args));
  28. }
  29. };
  30. };
  31. @Injectable()
  32. export class SceneService implements OnModuleInit, OnModuleDestroy {
  33. constructor(
  34. private configService: ConfigService,
  35. private cacheService: CacheService,
  36. private streamService: StreamService,
  37. private rotateService: RotateService,
  38. private moveService: MoveService,
  39. private getRouterService: GetRouterService, // @InjectQueue('rotate') private rotateQueue: Queue, // @InjectQueue('walking') private walkingQueue: Queue,
  40. ) {}
  41. @Client(grpcClientOptions) private readonly client: ClientGrpc;
  42. public _frameInteval: NodeJS.Timeout;
  43. public _frameTimeout: NodeJS.Timeout;
  44. public _rotateTimeout: NodeJS.Timeout;
  45. public _moveTimeout: NodeJS.Timeout;
  46. public _JoyStickingSteamTimeout: NodeJS.Timeout;
  47. public _packFrameTimeout: NodeJS.Timeout;
  48. public startSteaming = new BehaviorSubject<boolean>(false);
  49. public onRotating = new BehaviorSubject<boolean>(false);
  50. public onMoving = new BehaviorSubject<boolean>(false);
  51. public onJoysticking = new BehaviorSubject<boolean>(false);
  52. public frameCnt = new BehaviorSubject<number>(-1);
  53. private rotateframeCnt = -1;
  54. private moveframeCnt = -1;
  55. private joystickFrameCnt = -1;
  56. private rotateFirstIDR = true;
  57. private rotateStopThrottle = false; //防止多次瞬间解触发
  58. private rotateTimeStamp: number;
  59. private channel: DataChannel;
  60. private peer: PeerConnection;
  61. private logger: Logger = new Logger('SceneService');
  62. private frameCntInterval = 1000;
  63. private user_id: string;
  64. private roomId: string;
  65. private onSteaming = false;
  66. private mockserverTime = Date.now() - 1653000000478;
  67. private lastRenderMedia = '';
  68. private frameCntSubscription: any;
  69. private roQueueSubscription: any;
  70. private moveQueueSubscription: any;
  71. private walkingSub: any;
  72. private _rotateCountFame = -1;
  73. private _rotateStartFame = new BehaviorSubject<number>(-1);
  74. private _rotateCount = -1;
  75. private streamServiceSub: any;
  76. // private roRequestQueue: RxQueue = new DelayQueue(20);
  77. // private roQueue: RxQueue = new DelayQueue(
  78. // Number(this.configService.get('queueConfig.rotate')) || 20,
  79. // );
  80. private moveQueue: RxQueue = new DelayQueue(
  81. Number(this.configService.get('queueConfig.move')) || 20,
  82. );
  83. private requestIFrameQueue: RxQueue = new DebounceQueue(2000);
  84. private requestIFrameQueueSub: any;
  85. private roRequestQueueSub: any;
  86. private rewalking = false;
  87. private firstRender = false;
  88. private lastMovingPointArray: MovingLastUpdateType[] = [];
  89. private latestRotateRequest: any; // 最新Rotate的接收值
  90. private latestWalkingRequest: any; // 最新waking的接收值
  91. private hasJoystickMoveRequest = false; // 最新joystick的接收值
  92. private stopRotated = false;
  93. private moveSliceLastFrame = new BehaviorSubject<MovingLastUpdateType>(null);
  94. private moveSliceLastFrameSub: any;
  95. public lastMoveStreamFrame = new BehaviorSubject<StreamFrameType>({
  96. frame: -1,
  97. clipPath: '',
  98. metaData: '',
  99. });
  100. public testTimer = 0;
  101. private isJoystickHasStream = false;
  102. private hasJoystickFocusRepeat = false;
  103. private startSub: any;
  104. public users = {};
  105. public sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
  106. private globalOptLock = false;
  107. private isStopJointing = false;
  108. onModuleInit(): void {
  109. this.streamServiceSub = this.streamService.onSteaming.subscribe((val) => {
  110. this.onSteaming = val;
  111. });
  112. Number.prototype.padLeft = function (n, str) {
  113. return Array(n - String(this).length + 1).join(str || '0') + this;
  114. };
  115. // this.logger.log('roQueue-period :' + Number(this.roQueue.period));
  116. this.logger.log('moveQueue-period :' + Number(this.moveQueue.period));
  117. }
  118. public isHeaderOrLast(index: number, length: number): boolean {
  119. if (index === 0 || index === length) {
  120. return true;
  121. } else {
  122. return false;
  123. }
  124. }
  125. public getConfig() {
  126. return {
  127. userId: this.user_id,
  128. roomId: this.roomId,
  129. };
  130. }
  131. public startStream(): void {
  132. clearInterval(this._frameInteval);
  133. if (this.frameCnt.value === -1) {
  134. this._frameInteval = setInterval(async () => {
  135. const next = this.frameCnt.value + 1;
  136. this.frameCnt.next(next);
  137. }, 1000);
  138. }
  139. }
  140. public holdSteam(): void {
  141. clearInterval(this._frameInteval);
  142. }
  143. public resumeStream(): void {
  144. this.onMoving.next(false);
  145. this.onRotating.next(false);
  146. this.onJoysticking.next(false);
  147. this.moveframeCnt = -1;
  148. this.rotateframeCnt = -1;
  149. this.globalOptLock = false;
  150. clearInterval(this._frameInteval);
  151. this._frameInteval = setInterval(async () => {
  152. const next = this.frameCnt.getValue() + 1;
  153. this.frameCnt.next(next);
  154. }, 1000);
  155. }
  156. public stopStream(): void {
  157. if (this.frameCntSubscription) {
  158. this.frameCntSubscription.unsubscribe();
  159. this.frameCntSubscription = null;
  160. }
  161. if (this.roQueueSubscription) {
  162. this.roQueueSubscription.unsubscribe();
  163. this.roQueueSubscription = null;
  164. }
  165. if (this.moveQueueSubscription) {
  166. this.moveQueueSubscription.unsubscribe();
  167. this.moveQueueSubscription = null;
  168. }
  169. this.frameCnt.next(-1);
  170. clearInterval(this._frameInteval);
  171. this.rotateframeCnt = -1;
  172. }
  173. setConfig(user_id: string, roomId: string): void {
  174. this.user_id = user_id;
  175. this.roomId = roomId;
  176. }
  177. onModuleDestroy() {
  178. if ('unsubscribe' in this.streamServiceSub) {
  179. this.streamService.onSteaming.unsubscribe();
  180. }
  181. }
  182. init(request: InitRequest) {
  183. try {
  184. this.rotateService.init(
  185. request.app_id,
  186. request.user_id,
  187. request.skin_id,
  188. request.roomId,
  189. request.avatar_id,
  190. );
  191. this.cacheService.getClient();
  192. console.log('rotateService::init');
  193. this.startSub = this.startSteaming.subscribe((flag) => {
  194. if (flag) {
  195. console.log('初始推流::');
  196. this.startStream();
  197. this.handleStream();
  198. }
  199. });
  200. // 加载
  201. } catch (error) {
  202. this.logger.error('error', error);
  203. }
  204. }
  205. exit() {
  206. this.frameCnt.next(-1);
  207. this.rotateService.deleteUser(this.user_id);
  208. this.hasJoystickFocusRepeat = false;
  209. if (this.startSub) {
  210. this.startSub.unsubscribe();
  211. this.startSub = null;
  212. }
  213. }
  214. async rotate(request: RotateRequest) {
  215. if (this.isHasWalkingJoints()) {
  216. this.globalOptLock = true;
  217. } else {
  218. console.log('开锁rotate或正常rotate');
  219. }
  220. this.latestRotateRequest = request;
  221. // if (
  222. // this.onMoving.getValue() &&
  223. // this.globalOptLock &&
  224. // // this._rotateCount > 5 &&
  225. // !this.rotateStopThrottle
  226. // ) {
  227. // this.handleRotateStop(request);
  228. // // debugger;
  229. // }
  230. this.handleRotate(request);
  231. this._rotateCount += 1;
  232. }
  233. /**
  234. * rotate请求队列
  235. */
  236. async handleRotate(request) {
  237. // try {
  238. const rotateUnlock = this.firstRender && !this.globalOptLock;
  239. console.log('rotateUnlock条件--->' + rotateUnlock, this.globalOptLock);
  240. if (rotateUnlock && this._rotateCount > 2) {
  241. console.log('20220627test:handleRotate');
  242. const start = performance.now();
  243. // 当move时处理 _rotateCount是移动端同时触发的问题,rotateStopThrottle是减少重复抖动stop的处理。
  244. this.holdSteam();
  245. const redisMeta: StreamReplyType = await this.rotateService.seqExeRotate(
  246. request,
  247. );
  248. if (redisMeta && 'mediaSrc' in redisMeta) {
  249. if (redisMeta.mediaSrc?.length) {
  250. const src = redisMeta.mediaSrc.split('?')[0];
  251. if (src.length > 0) {
  252. this.lastRenderMedia = src;
  253. const clipPath = this.configService.get('app.prefix') + src;
  254. delete redisMeta.mediaSrc;
  255. const stream: StreamFrameType = {
  256. frame: -1,
  257. clipPath: clipPath,
  258. metaData: JSON.stringify(redisMeta),
  259. serverTime: this.mockserverTime,
  260. DIR: 3,
  261. };
  262. const stop = performance.now();
  263. const inMillSeconds = stop - start;
  264. const rounded = Number(inMillSeconds).toFixed(3);
  265. this.logger.log(
  266. `[timer]-rotate-入队列前: ${rounded}ms -->` +
  267. JSON.stringify(stream),
  268. );
  269. if (!this.stopRotated) {
  270. await this.seqExehandleRotateStream(stream);
  271. }
  272. // this.roQueue.next(stream);
  273. } else {
  274. this.onRotating.next(false);
  275. }
  276. }
  277. }
  278. } else {
  279. return;
  280. }
  281. // } catch (error) {
  282. // this.logger.error('rotate', error.message);
  283. // console.error('error', error);
  284. // }
  285. }
  286. handleStopRotate() {
  287. this.stopRotated = true;
  288. }
  289. resumeRotate() {
  290. this.stopRotated = false;
  291. }
  292. seqExehandleRotateStream = seqExeAsyncFn(this.handleRotateStream);
  293. /**
  294. * rotate 推送seq(不存在队列,直推)
  295. */
  296. async handleRotateStream(stream: StreamFrameType) {
  297. this.rotateTimeStamp = Date.now();
  298. this.holdSteam();
  299. // 在未开始前开始
  300. if (!this.onRotating.value) {
  301. this._rotateStartFame.next(this.frameCnt.value);
  302. console.log('旋转开始记录帧:::--->', this._rotateStartFame.value);
  303. }
  304. this.onRotating.next(true);
  305. stream.frame = this.frameCnt.value + 1;
  306. // 从记录第一帧到最新一帧
  307. this._rotateCountFame = stream.frame - this._rotateStartFame.value;
  308. const IDRflag = this._rotateCountFame % 5 === 0 ? 1 : 3;
  309. stream.DIR = this.rotateFirstIDR ? 1 : IDRflag;
  310. console.log(
  311. '[旋转信息:::info--->]:clipPath: %s, main-frameCnt: %s, stream.frame %s ,_rotateStartFame: %s, _rotateCountFame: %s, IDRflag: %s,time: %s',
  312. stream.clipPath,
  313. // this._rotateStartFame.value,
  314. this.frameCnt.value,
  315. stream.frame,
  316. this._rotateStartFame.value,
  317. this._rotateCountFame,
  318. // this.rotateframeCnt,
  319. IDRflag,
  320. new Date().getTime(),
  321. );
  322. const res = await this.streamService.pushFrameToSteam(stream);
  323. if (res.done) {
  324. this.frameCnt.next(res.frame);
  325. if (this.rotateFirstIDR) {
  326. this.rotateFirstIDR = false;
  327. }
  328. console.log('[旋转信息:::info:::done--->]', res);
  329. clearTimeout(this._rotateTimeout);
  330. this._rotateTimeout = setTimeout(() => {
  331. this.logger.log('rotate end', Date.now());
  332. this.rotateframeCnt = -1;
  333. this._rotateCountFame = -1;
  334. this._rotateCount = 0;
  335. this.latestRotateRequest = null;
  336. this.rotateFirstIDR = true;
  337. this.resumeStream();
  338. }, 200);
  339. } else {
  340. console.error('流地址有误::', res.frame, JSON.stringify(res));
  341. this.logger.error('流地址有误::', res.frame, JSON.stringify(res));
  342. this.resumeStream();
  343. }
  344. }
  345. // /**
  346. // * rotate 推送队列 --backup
  347. // */
  348. // handleRotateStream() {
  349. // if (!this.roQueueSubscription) {
  350. // this.roQueueSubscription = this.roQueue.subscribe(
  351. // async (stream: StreamFrameType) => {
  352. // this.rotateTimeStamp = Date.now();
  353. // if (this.rotateframeCnt === -1) {
  354. // this.rotateframeCnt = this.frameCnt.value;
  355. // }
  356. // this.rotateframeCnt += 1;
  357. // stream.frame = this.rotateframeCnt;
  358. // this._rotateCountFame += 1;
  359. // const IDRflag = this._rotateCountFame % 5 === 0 ? 1 : 3;
  360. // this.logger.log(
  361. // `当前rotate ,mainframeCnt:${this.frameCnt.getValue()}, _rotateCountFame:${this._rotateCountFame
  362. // } IDRflag:${IDRflag}`,
  363. // );
  364. // stream.DIR = this.rotateFirstIDR ? 1 : IDRflag;
  365. // if (this.rotateFirstIDR) {
  366. // this.rotateFirstIDR = false;
  367. // }
  368. // this.logger.log(
  369. // '[media-rotate]: ' +
  370. // ', frame: ' +
  371. // stream.frame +
  372. // ', rotateframeCnt: ' +
  373. // this.rotateframeCnt +
  374. // ', clipPath: ' +
  375. // stream.clipPath,
  376. // // stream.metaData,
  377. // );
  378. // // this.logger.log(
  379. // // `roQueueSubscription:frame:${this.rotateframeCnt} ` +
  380. // // JSON.stringify(stream.metaData),
  381. // // );
  382. // const res = await this.streamService.pushFrameToSteam(stream);
  383. // if (res.done) {
  384. // clearTimeout(this._rotateTimeout);
  385. // this._rotateTimeout = setTimeout(() => {
  386. // this.logger.log('rotate end', Date.now());
  387. // this.frameCnt.next(res.frame);
  388. // this.rotateframeCnt = -1;
  389. // this._rotateCountFame = -1;
  390. // // this.onMoving.next(false);
  391. // // this.onRotating.next(false);
  392. // this.latestRotateRequest = null;
  393. // this.rotateFirstIDR = true;
  394. // this.resumeStream();
  395. // //TODO rotate完后清除request队列
  396. // if (this.roRequestQueueSub) {
  397. // this.roRequestQueueSub.unsubscribe();
  398. // this.roRequestQueueSub = null;
  399. // }
  400. // }, 100);
  401. // } else {
  402. // console.error('流地址有误::', res.frame, JSON.stringify(res));
  403. // this.logger.error('流地址有误::', res.frame, JSON.stringify(res));
  404. // this.resumeStream();
  405. // }
  406. // },
  407. // );
  408. // }
  409. // }
  410. /**
  411. * 旋转中断逻辑
  412. * 1. 行走间
  413. * 1.1 行走间中断只能在每段最后一帧,当前段一定要消费掉,在未消费,globalOptLock锁rotate,消费完 rotate
  414. * 1.2 消费完要处理点位上传,清除当前段往后的都要清掉,回调各种stop function
  415. * 2.joystick间 complementFrame pools 解锁就可以
  416. */
  417. async handleRotateOrWalkingStop(request): Promise<boolean> {
  418. this.rotateStopThrottle = true;
  419. this.isStopJointing = true;
  420. const lastStreamFrame = this.lastMoveStreamFrame.getValue();
  421. this.logger.log(
  422. 'handleRotateOrWalkingStop-frame',
  423. JSON.stringify(lastStreamFrame),
  424. );
  425. const metaData: StreamReplyType = JSON.parse(
  426. lastStreamFrame.metaData,
  427. ) as any as StreamReplyType;
  428. if (!metaData.endBreakPointId) {
  429. }
  430. console.log('stop-4', metaData.traceIds[0]);
  431. console.log('stop-5', request.trace_id);
  432. //判断request是否是新的
  433. if (metaData.traceIds.indexOf(request.trace_id) > -1) {
  434. return Promise.resolve(false);
  435. }
  436. console.log('currentUser-user_id', this.user_id);
  437. const newUserStates: NewUserStatesType = metaData.newUserStates.find(
  438. (item) => item.userId === this.user_id,
  439. );
  440. const trace_id = metaData.traceIds[0];
  441. const userId = newUserStates.userId;
  442. //TODO 临时,可能数据会不对
  443. const breakPointId = metaData.endBreakPointId || metaData.breakPointId;
  444. const cameraAngle = newUserStates.playerState.camera.angle;
  445. const playerAngle = newUserStates.playerState.player.angle;
  446. this.logger.log(
  447. 'stop-data-0' +
  448. 'trace_id: ' +
  449. trace_id +
  450. 'userId:' +
  451. userId +
  452. 'breakPointId :' +
  453. breakPointId +
  454. 'cameraAngle :' +
  455. JSON.stringify(cameraAngle) +
  456. 'playerAngle: ' +
  457. JSON.stringify(playerAngle),
  458. );
  459. //debugger;
  460. console.log('moveService.stop-1:' + breakPointId);
  461. //console.log('20220627test:handleRotateOrWalkingStop-stop');
  462. const redisMeta = await this.moveService.stop(
  463. trace_id,
  464. userId,
  465. breakPointId,
  466. cameraAngle,
  467. playerAngle,
  468. );
  469. this.logger.log('stop-redisMeta-frame', JSON.stringify(redisMeta));
  470. if (redisMeta) {
  471. const src = redisMeta.mediaSrc.split('?')[0];
  472. const mediaSrc = this.configService.get('app.prefix') + src;
  473. const streamData: StreamFrameType = {
  474. frame: this.frameCnt.value + 1,
  475. clipPath: mediaSrc,
  476. metaData: JSON.stringify(redisMeta),
  477. serverTime: this.mockserverTime,
  478. DIR: 1,
  479. };
  480. //推最后一个 STOP Frame
  481. const hasPush = await this.streamService.pushFrameToSteam(streamData);
  482. if (hasPush.done) {
  483. //console.log('20220627test:handleRotateOrWalkingStop-stop:'+streamData.clipPath+'**'+streamData.frame);
  484. this.frameCnt.next(hasPush.frame);
  485. this.isStopJointing = false;
  486. // this.onMoving.next(false);
  487. // this.cleanMoveSteam();
  488. return Promise.resolve(true);
  489. // this.resumeStream();
  490. } else {
  491. console.error(
  492. '暂停STOP::帧有问题',
  493. hasPush.frame,
  494. JSON.stringify(streamData),
  495. );
  496. return Promise.resolve(false);
  497. }
  498. }
  499. }
  500. async getSimplestCameraInfo(appId,userId){
  501. if(this.moveService.cameraInfos.length>20){
  502. const startBreakPointId = this.moveService.cameraInfos[0].startBreakPointId;
  503. const endBreakPointId = this.moveService.cameraInfos[this.moveService.cameraInfos.length-1].endBreakPointId;
  504. const path = this.getRouterService.searchRoad2(startBreakPointId,endBreakPointId);
  505. if(path == null){
  506. //可以清空cameraInfos
  507. this.moveService.cameraInfos = [];
  508. }
  509. else{
  510. await this.moveService.updateCameraInfoForDely(appId,userId,path);
  511. }
  512. }
  513. }
  514. /**
  515. * 行走动作
  516. *
  517. * @param request
  518. */
  519. async walking(request: MoveRequest) {
  520. this.latestWalkingRequest = request;
  521. this.logger.log('walking-trace_id', request.trace_id);
  522. // if (this.isHasWalkingJoints()) {
  523. // console.log('lock-锁-walking', this.latestWalkingRequest);
  524. // this.globalOptLock = true;
  525. // }
  526. // 进入正常walking流程
  527. if (!this.onMoving.getValue()) {
  528. console.log('walking-step-main-1', request.trace_id);
  529. this.latestWalkingRequest = null;
  530. this.handleWalking(request);
  531. } else {
  532. this.globalOptLock = true;
  533. console.log('lock-锁-walking', this.latestWalkingRequest);
  534. }
  535. this.handleWalkingJoints();
  536. }
  537. /**
  538. * 一段walking每个Joints关节点
  539. * @param request
  540. */
  541. handleWalkingJoints() {
  542. // 每个关节点
  543. if (!this.moveSliceLastFrameSub) {
  544. this.moveSliceLastFrameSub = this.moveSliceLastFrame.subscribe(
  545. async (frame: MovingLastUpdateType) => {
  546. //TODO 正在行走时,有新的reqest
  547. if (frame) {
  548. // console.log('unlock-Joints', JSON.stringify(frame));
  549. this.logger.log('Joints', JSON.stringify(frame));
  550. this.resumeRotate();
  551. let isRotateStop = false;
  552. let isWalkingStop = false;
  553. // 在全局锁的情况下
  554. if (this.globalOptLock) {
  555. isRotateStop = !!this.latestRotateRequest && this.onMoving.value;
  556. isWalkingStop =
  557. !!this.latestWalkingRequest && this.onMoving.value;
  558. console.log('g--isRotateStop', isRotateStop);
  559. console.log('g--isWalkingStop', isWalkingStop);
  560. // 这个就是双暂时出现的时候, 强制只执行一次,以isWalkingStop为主
  561. if (isRotateStop && isWalkingStop) {
  562. isRotateStop = false;
  563. }
  564. console.log('g--1-isRotateStop', isRotateStop);
  565. console.log('g--1-isWalkingStop', isWalkingStop);
  566. // 这个旋转暂停
  567. if (isRotateStop) {
  568. const hasStop = await this.handleRotateOrWalkingStop(
  569. this.latestRotateRequest,
  570. );
  571. console.log('旋转-hasStop', hasStop);
  572. this.clearWalkingJoints();
  573. this.cleanMoveSteam();
  574. this.globalOptLock = false;
  575. }
  576. // 这个行走暂停
  577. if (isWalkingStop) {
  578. const hasStop = await this.handleRotateOrWalkingStop(
  579. this.latestWalkingRequest,
  580. );
  581. console.log('walking-hasStop', hasStop);
  582. this.clearWalkingJoints();
  583. this.cleanMoveSteam();
  584. this.globalOptLock = false;
  585. console.log('unlock-walking');
  586. this.handleReWalking(this.latestWalkingRequest);
  587. // console.log('this', this.rewalking);
  588. }
  589. }
  590. }
  591. },
  592. );
  593. }
  594. }
  595. /**
  596. * 清除所有的节点信信息
  597. * @param request
  598. */
  599. clearWalkingJoints() {
  600. this.moveSliceLastFrame.next(null);
  601. this.lastMovingPointArray = [];
  602. }
  603. /**
  604. * 是否有行走关节点
  605. * @returns boolean
  606. */
  607. isHasWalkingJoints(): boolean {
  608. return this.lastMovingPointArray.length > 0;
  609. }
  610. /**
  611. * 行走队列处理器
  612. * @param request MoveRequest
  613. * @returns void
  614. */
  615. async handleWalking(request: MoveRequest): Promise<void> {
  616. try {
  617. // if (!this.onMoving.getValue()) {
  618. console.log('walking-step-main-2', request.trace_id);
  619. const start = performance.now();
  620. this._rotateCount = 0;
  621. const user = this.moveService.users[this.user_id];
  622. console.log('进入1 - searchRoad');
  623. this.logger.log(
  624. 'handleWalking-users' +
  625. JSON.stringify(this.moveService.users) +
  626. ' this.user_id: ' +
  627. this.user_id,
  628. );
  629. this.logger.log(
  630. 'handleWalking-currentUser' +
  631. JSON.stringify(user) +
  632. ' this.user_id: ' +
  633. this.user_id,
  634. );
  635. console.log('path-start' + user.breakPointId);
  636. const path = await this.getRouterService.searchRoad(
  637. user.appId,
  638. user.breakPointId,
  639. request.clicking_action.clicking_point,
  640. );
  641. this.logger.log('walking-path', path);
  642. if (!path) {
  643. console.log('不存在--path', path);
  644. this.cleanMoveSteam();
  645. this.clearWalkingJoints();
  646. this.resumeRotate();
  647. this.resumeStream();
  648. return;
  649. }
  650. // debugger;
  651. const walkingRes = await this.moveService.move(path, request);
  652. if (walkingRes && (!this.onMoving.value || this.rewalking)) {
  653. // 二维数组 做move 序列, move类型
  654. //console.log('move-walkingRes:' + JSON.stringify(walkingRes));
  655. this.handleStopRotate();
  656. if (walkingRes && walkingRes?.length >= 1) {
  657. for (let i = 0; i <= walkingRes.length - 1; i++) {
  658. Array.from(walkingRes[i]).forEach(
  659. (item: StreamReplyType, index: number) => {
  660. console.log(
  661. '20220628test:handleWalking->' +
  662. item['newUserStates'][0].renderInfo.isMoving,
  663. );
  664. //const IDRflag = index % 5 === 0 ? 1 : 3;
  665. const IDRflag = item.isIDR ? 1 : 3;
  666. const dir = this.isHeaderOrLast(
  667. index,
  668. walkingRes[i].length - 1,
  669. );
  670. item.DIR = dir ? 1 : IDRflag;
  671. //将每段最后一个推入lastMovingPointArray
  672. if (index === walkingRes[i].length - 1) {
  673. this.lastMovingPointArray.push({
  674. mediaSrc: item.mediaSrc,
  675. metaData: item,
  676. });
  677. }
  678. },
  679. );
  680. }
  681. }
  682. // walkingRes marker to everybody
  683. const seqs = Array.from(walkingRes).flat() as any as StreamReplyType[];
  684. if (seqs?.length) {
  685. this.logger.log(
  686. 'walking --队列总览:' +
  687. ' 总段数: ' +
  688. walkingRes.length +
  689. ' 镜头帧数:' +
  690. walkingRes[0].length +
  691. ' 行走段数:' +
  692. (walkingRes[0]?.length
  693. ? walkingRes.length - 1
  694. : walkingRes.length) +
  695. ' 队列总帧数:' +
  696. seqs.length,
  697. );
  698. const stop = performance.now();
  699. const inMillSeconds = stop - start;
  700. const rounded = Number(inMillSeconds).toFixed(3);
  701. this.logger.log(`[timer]-move-入队列前:-->${rounded}ms`);
  702. this.handleSeqMoving(seqs);
  703. } else {
  704. console.error('walking-move无数据');
  705. this.cleanMoveSteam();
  706. this.resumeStream();
  707. }
  708. // }
  709. }
  710. // });
  711. // }
  712. } catch (error) {
  713. this.logger.error('walking', error.message);
  714. this.cleanMoveSteam();
  715. this.resumeStream();
  716. }
  717. }
  718. /**
  719. * 改变路线后的walking队列处理(中转)
  720. * @param request MoveRequest
  721. */
  722. handleReWalking(request: MoveRequest) {
  723. // this.latestWalkingRequest = null;
  724. this.rewalking = true;
  725. this.handleWalking(request);
  726. }
  727. /***
  728. * joystick main core
  729. */
  730. async joystick(request: JoystickRequest) {
  731. // TODO hasJoystickMoveRequest中断
  732. this.logger.log('this.hasJoystickMoveRequest', this.hasJoystickMoveRequest);
  733. if (!this.hasJoystickMoveRequest) {
  734. this.handlejoystick(request);
  735. }
  736. }
  737. /**
  738. * joystick 二合一推流
  739. * @param joystickRes StreamMetaType | StreamFrameType;
  740. */
  741. handlePushJoyStickSteamSeq = seqExeAsyncFn(this.handlePushJoyStickSteam);
  742. async handlePushJoyStickSteam(joystickRes: StreamReplyType) {
  743. this.holdSteam();
  744. this.globalOptLock = true;
  745. //console.log('joystickRes有mediaSrc', joystickRes.mediaSrc);
  746. console.log(
  747. 'handlejoystick-angle->相机角度-------------------------:' +
  748. joystickRes['newUserStates'][0].playerState.camera.angle.yaw,
  749. );
  750. let streamData: StreamFrameType | StreamMetaType;
  751. this.joystickFrameCnt = this.frameCnt.getValue() + 1;
  752. const hasMedia = joystickRes?.mediaSrc && joystickRes?.mediaSrc.length > 0;
  753. if (hasMedia) {
  754. const src = joystickRes.mediaSrc.split('?')[0];
  755. const mediaSrc = this.configService.get('app.prefix') + src;
  756. // IDR flag设置为I帧
  757. const setDIR = joystickRes.isIDR ? 1 : 3;
  758. streamData = {
  759. frame: this.joystickFrameCnt,
  760. clipPath: mediaSrc,
  761. metaData: JSON.stringify(joystickRes),
  762. serverTime: this.mockserverTime,
  763. DIR: setDIR,
  764. };
  765. console.log(
  766. 'handlejoystick-hasMedia->-------------------------:' +
  767. ' frame: ' +
  768. streamData.frame +
  769. mediaSrc +
  770. ' IDR :' +
  771. setDIR,
  772. );
  773. } else {
  774. streamData = {
  775. frame: this.joystickFrameCnt,
  776. metaData: JSON.stringify(joystickRes),
  777. };
  778. }
  779. console.log(
  780. '20220627test-complementFrame 进行1' + '***' + streamData.frame,
  781. );
  782. // 过滤新东西, 推完给回false
  783. this.moveService.sendingFrameForJoystick = true;
  784. const hasPush = hasMedia
  785. ? await this.streamService.pushFrameToSteam(streamData as StreamFrameType)
  786. : await this.streamService.pushMetaDataToSteam(
  787. streamData as StreamMetaType,
  788. );
  789. if (hasPush.done) {
  790. this.isJoystickHasStream = true;
  791. console.log('joystick-hasPush', hasPush);
  792. // if (this.isJoystickHasStream) {
  793. // await this.sleep(20);
  794. // }
  795. // await this.sleep(20);
  796. this.frameCnt.next(hasPush.frame);
  797. this.moveService.sendingFrameForJoystick = false;
  798. const data = joystickRes as StreamReplyType;
  799. console.log('handlejoystick-isIDR:' + data.isIDR);
  800. // if (data?.moveOver && data.moveOver) {
  801. // // moveOver
  802. // console.log('回传updateUser', data);
  803. // // const userId = this.user_id;
  804. // // 回传点暂时有问题,待修复
  805. // //const breakPointId = data.endBreakPointId || data.breakPointId;
  806. // //const lastReply = JSON.stringify(joystickRes);
  807. // //this.moveService.updateUser(userId, breakPointId, lastReply);
  808. // }
  809. /**
  810. * 这个complementFrame 具体说明 pools 是complementFrame这个返回值
  811. * 1. 第一次要在200ms后调用, 如有值(pools) 就要返回主流程执行,但设置hasJoystickFocusRepeat为true
  812. * 2. 第二次或N进入在hasJoystickFocusRepeat为true并绕过200ms timeout,如pools有值返回(2)主流程直到pools为null
  813. * 3. 如pools为空走回 200ms流程 (这时pools应该为空),交权回空流。
  814. */
  815. if (this.hasJoystickFocusRepeat) {
  816. const complementFrame = this.moveService.complementFrame(
  817. this.user_id,
  818. ) as StreamReplyType;
  819. if (complementFrame) {
  820. console.log(
  821. '20220627test-complementFrame 进行' +
  822. complementFrame.mediaSrc +
  823. '***' +
  824. this.frameCnt.value,
  825. );
  826. // 第二次或N次进入时如果有值直接重新进入流主程
  827. this.holdSteam();
  828. this.handlePushJoyStickSteamSeq(complementFrame);
  829. this.globalOptLock = true;
  830. } else {
  831. console.log('20220627test-complementFrame 结束');
  832. // 第二次或N次无pool数据再次trigger handleJoystickStop
  833. this.hasJoystickFocusRepeat = false;
  834. this.testTimer = 0;
  835. //this.handleJoystickStop(hasPush);
  836. this.globalOptLock = false;
  837. this.resumeStream();
  838. }
  839. } else {
  840. this.handleJoystickStop(hasPush);
  841. }
  842. } else {
  843. console.error('joystick-流地址有误::', joystickRes.mediaSrc);
  844. this.logger.error('joystick-流地址有误::', joystickRes.mediaSrc);
  845. this.resumeStream();
  846. }
  847. }
  848. /**
  849. * Joystick Stop function
  850. */
  851. async handleJoystickStop(hasPush: StreamPushResponse) {
  852. // 最后一帧200ms
  853. clearTimeout(this._JoyStickingSteamTimeout);
  854. this._JoyStickingSteamTimeout = setTimeout(async () => {
  855. console.log('20220627test-complementFrame handleJoystickStop 200ms之后');
  856. const user = this.moveService.users[this.user_id];
  857. await this.getSimplestCameraInfo(user.appId,this.user_id);
  858. const complementFrame = this.moveService.complementFrame(
  859. this.user_id,
  860. ) as StreamReplyType;
  861. // console.log('has-complementFrame', complementFrame);
  862. console.log('gemer-test-complementFrame', complementFrame);
  863. if (complementFrame) {
  864. this.hasJoystickFocusRepeat = true;
  865. this.globalOptLock = true;
  866. this.testTimer += 1;
  867. console.log('complementFrame-有值');
  868. const start = performance.now();
  869. this.handlePushJoyStickSteamSeq(complementFrame);
  870. const stop = performance.now();
  871. console.log('handlePushJoyStickSteam', this.testTimer);
  872. const inMillSeconds = stop - start;
  873. const rounded = Number(inMillSeconds).toFixed(3);
  874. console.log(`complementFrame调用时间---->${rounded}`);
  875. } else {
  876. console.log('complementFrame-空1');
  877. this.logger.log('joystick opt done');
  878. this.logger.log('joystick 交权给空流,当前pts', hasPush.frame);
  879. this.hasJoystickFocusRepeat = false;
  880. this.onJoysticking.next(false);
  881. this.resumeStream();
  882. this.joystickFrameCnt = -1;
  883. this.isJoystickHasStream = false;
  884. }
  885. }, 200);
  886. }
  887. /***
  888. * joystick
  889. */
  890. async handlejoystick(request: JoystickRequest) {
  891. try {
  892. //const joystickRes = await this.moveService.joystick(request);
  893. this._rotateCount = 0;
  894. const joystickRes = await this.moveService.seqExeJoystick(request);
  895. this.logger.log(
  896. 'joystick-breakPointId:' +
  897. this.moveService.users[this.user_id].breakPointId,
  898. );
  899. // 有数据 [0]是rotate数据,[1-infinity]是walking数据
  900. //this.logger.log('joystickRes', JSON.stringify(joystickRes));
  901. if (joystickRes) {
  902. this.onJoysticking.next(true);
  903. // console.log(
  904. // 'handlejoysticktesttest:' +
  905. // joystickRes.mediaSrc +
  906. // ',相机坐标:' +
  907. // JSON.stringify(
  908. // joystickRes.newUserStates[0].playerState.player.position,
  909. // ),
  910. // );
  911. if (!this.onMoving.getValue()) {
  912. console.log('handlejoystick:data', JSON.stringify(joystickRes));
  913. this.handlePushJoyStickSteamSeq(joystickRes);
  914. }
  915. } else {
  916. console.log('handlejoystick:null');
  917. this.onJoysticking.next(false);
  918. }
  919. } catch (error) {
  920. console.error('joystick错误', error);
  921. this.onJoysticking.next(false);
  922. this.logger.error('joystick', error.message);
  923. }
  924. }
  925. /**
  926. * 主要处理moving的序列动作
  927. * @param seqs StreamReplyType[]
  928. */
  929. handleSeqMoving(seqs: StreamReplyType[]) {
  930. // if (!this.moveQueueSubscription) {
  931. // this.handleMoveSteam();
  932. // }
  933. // this.logger.log('moving-seqs', seqs.length);
  934. this.onMoving.next(true);
  935. this.holdSteam();
  936. // 保证每一段都是序列动作的前面队列是空的
  937. // this.moveQueue.clean();
  938. seqs.forEach((frame: StreamReplyType) => {
  939. const mediaSrc = frame.mediaSrc;
  940. const src = mediaSrc.split('?')[0];
  941. const clipPath = this.configService.get('app.prefix') + src;
  942. const type = frame.mType?.length ? frame.mType.slice() : 'move';
  943. const stream: StreamFrameType = {
  944. frame: -1,
  945. clipPath: clipPath,
  946. metaData: JSON.stringify(frame),
  947. serverTime: this.mockserverTime,
  948. DIR: frame.DIR,
  949. mType: type,
  950. };
  951. // this.moveQueue.next(stream);
  952. this.handleMoveSteam(stream);
  953. });
  954. }
  955. handleMoveSteam = seqExeAsyncFn(this.handleMoveSteamFn);
  956. async handleMoveSteamFn(stream: StreamFrameType) {
  957. try {
  958. if (!this.isStopJointing) {
  959. const metaData: StreamReplyType = JSON.parse(stream.metaData);
  960. // if (this.moveframeCnt === -1) {
  961. // this.moveframeCnt = this.frameCnt.getValue();
  962. // }
  963. // this.moveframeCnt += 1;
  964. // this.latestBreakPointId = metaData.endBreakPointId;
  965. this.moveframeCnt = this.frameCnt.value + 1;
  966. const streamData: StreamFrameType = {
  967. frame: this.moveframeCnt,
  968. clipPath: stream.clipPath,
  969. metaData: stream.metaData,
  970. serverTime: this.mockserverTime,
  971. DIR: stream.DIR,
  972. };
  973. this.logger.log(
  974. '[media-move]: ' +
  975. ', moveframeCnt: ' +
  976. this.moveframeCnt +
  977. ', clipPath: ' +
  978. stream.clipPath +
  979. ', mType: ' +
  980. stream.mType +
  981. ', DIR: ' +
  982. stream.DIR,
  983. // stream.metaData,
  984. );
  985. this.logger.log(
  986. '[media-move-lastMovingPointArray]',
  987. this.lastMovingPointArray?.length,
  988. );
  989. // 记录lastMoveStreamFrame给打断逻辑使用
  990. this.lastMoveStreamFrame.next(streamData);
  991. // this.lastMoveStreamFrameBk = streamData;
  992. this.holdSteam();
  993. // this.globalOptLock = true;
  994. //console.log('20220627test:handleMoveSteam:' + stream.clipPath)
  995. const frameTimeStart = performance.now();
  996. const res = await this.streamService.pushFrameToSteam(streamData);
  997. const isLastFrameIndex = this.lastMovingPointArray.findIndex(
  998. (item) => item.mediaSrc === metaData.mediaSrc,
  999. );
  1000. // this.logger.log('path-update-index', isLastFrameIndex);
  1001. if (res.done) {
  1002. const frameTimeEnd = performance.now();
  1003. const frameAverage = frameTimeEnd - frameTimeStart;
  1004. console.log('walking-frameAverage', frameAverage);
  1005. await this.sleep(40);
  1006. this.frameCnt.next(res.frame);
  1007. //关节点入库
  1008. if (isLastFrameIndex > -1) {
  1009. //this.logger.log('path-update-array', this.lastMovingPointArray);
  1010. const currentMeta = this.lastMovingPointArray[isLastFrameIndex];
  1011. const userId = this.user_id;
  1012. const breakPointId = currentMeta.metaData.endBreakPointId;
  1013. const lastReply = currentMeta.metaData;
  1014. this.moveService.updateUser(userId, breakPointId, lastReply);
  1015. this.lastMovingPointArray.splice(isLastFrameIndex, 1);
  1016. this.moveSliceLastFrame.next(currentMeta);
  1017. }
  1018. clearTimeout(this._moveTimeout);
  1019. this._moveTimeout = setTimeout(() => {
  1020. this.logger.log('move 交权给空流,当前pts', res.frame);
  1021. this.rewalking = false;
  1022. this.frameCnt.next(res.frame);
  1023. this.rotateframeCnt = -1;
  1024. this.onMoving.next(false);
  1025. this.onJoysticking.next(false);
  1026. this.lastMovingPointArray = [];
  1027. this.hasJoystickMoveRequest = false;
  1028. this.cleanMoveSteam();
  1029. this.globalOptLock = false;
  1030. this.resumeStream();
  1031. this.logger.log('move end');
  1032. }, 200);
  1033. } else {
  1034. console.error('流地址有误::', res.frame, JSON.stringify(res));
  1035. this.logger.error(
  1036. `movesteam::当前帧:${res.frame}` + JSON.stringify(res),
  1037. );
  1038. this.resumeStream();
  1039. }
  1040. }
  1041. } catch (error) {
  1042. this.logger.error('handleMoveSteam::error', error);
  1043. }
  1044. }
  1045. cleanMoveSteam() {
  1046. this.moveQueue.clean();
  1047. if (this.moveQueueSubscription) {
  1048. this.moveQueueSubscription.unsubscribe();
  1049. this.moveQueueSubscription = null;
  1050. }
  1051. if (this.walkingSub) {
  1052. this.walkingSub.unsubscribe();
  1053. this.walkingSub = null;
  1054. }
  1055. if (this.moveSliceLastFrameSub) {
  1056. this.lastMoveStreamFrame.next(null);
  1057. this.moveSliceLastFrameSub.unsubscribe();
  1058. this.moveSliceLastFrameSub = null;
  1059. }
  1060. // if (this.clickQueueSub) {
  1061. // this.clickQueueSub.unsubscribe();
  1062. // this.clickQueueSub = null;
  1063. // }
  1064. this.rotateStopThrottle = false;
  1065. }
  1066. handleDataChanelOpen(channel: DataChannel, peer: PeerConnection): void {
  1067. this.channel = channel;
  1068. this.peer = peer;
  1069. this.streamService.setChannel(channel);
  1070. this.startSteaming.next(true);
  1071. // this.startStream();
  1072. // this.handleStream();
  1073. this.channel.onBufferedAmountLow(() => {
  1074. console.error('onBufferedAmountLow-rtt', this.peer.rtt());
  1075. console.error('onBufferedAmountLow', this.channel.bufferedAmount());
  1076. //64k->65536 128k->131072
  1077. this.channel.setBufferedAmountLowThreshold(262144);
  1078. this.logger.error('onBufferedAmountLow', this.channel.bufferedAmount());
  1079. });
  1080. }
  1081. handleDataChanelClose(): void {
  1082. this.stopStream();
  1083. this.startSteaming.next(false);
  1084. this.streamService.closeChannel();
  1085. this.cleanMoveSteam();
  1086. // const exitRequest: ExitRequest = {
  1087. // action_type: 1002,
  1088. // user_id: this.user_id,
  1089. // trace_id: '',
  1090. // };
  1091. this.exit();
  1092. }
  1093. handleMessage(message: string | Buffer) {
  1094. try {
  1095. if (typeof message === 'string') {
  1096. // wasm:特例, requestIframe
  1097. if (message.includes('wasm:')) {
  1098. const parseData = message
  1099. ? String(message).replace('wasm:', '')
  1100. : `{"MstType":1}`;
  1101. const msg: RTCMessageRequest = JSON.parse(parseData);
  1102. this.logger.error('lostIframe-message', JSON.stringify(msg));
  1103. if (Number(msg.MstType) === 0) {
  1104. this.handleIframeRequest();
  1105. }
  1106. } else {
  1107. const msg: RTCMessageRequest = JSON.parse(message);
  1108. // console.log('msg.action_type:' + msg.action_type);
  1109. switch (msg.action_type) {
  1110. case ActionType.walk:
  1111. const walk = msg as any as MoveRequest;
  1112. this.walking(walk);
  1113. break;
  1114. case ActionType.joystick:
  1115. const JoystickRequest = msg as any as JoystickRequest;
  1116. this.joystick(JoystickRequest);
  1117. break;
  1118. case ActionType.breathPoint:
  1119. this.handleBreath(msg);
  1120. break;
  1121. case ActionType.rotate:
  1122. const rotateRequest: RotateRequest = msg;
  1123. this.rotate(rotateRequest);
  1124. break;
  1125. case ActionType.userStatus:
  1126. this.updateUserStatus(msg);
  1127. break;
  1128. case ActionType.status:
  1129. this.updateStatus();
  1130. break;
  1131. default:
  1132. break;
  1133. }
  1134. }
  1135. }
  1136. } catch (error) {
  1137. this.logger.error('handleMessage:rtc--error', error.message);
  1138. }
  1139. }
  1140. async handleIframeRequest() {
  1141. //TODO Iframe 最终传什么?
  1142. this.holdSteam();
  1143. this.requestIFrameQueue.next(this.streamService.lastStreamFrame.getValue());
  1144. if (!this.requestIFrameQueueSub) {
  1145. this.requestIFrameQueueSub = this.requestIFrameQueue.subscribe(
  1146. async (frameData: StreamFrameType) => {
  1147. if (frameData) {
  1148. this.globalOptLock = true;
  1149. const nextFrame = this.frameCnt.getValue() + 1;
  1150. this.logger.warn('lostIframe', nextFrame);
  1151. frameData.frame = nextFrame;
  1152. frameData.DIR = 1;
  1153. const res = await this.streamService.pushFrameToSteam(frameData);
  1154. if (res.done) {
  1155. this.logger.error(
  1156. ' frame:' + res.frame + ' 补帧::' + JSON.stringify(frameData),
  1157. );
  1158. this.frameCnt.next(res.frame);
  1159. clearTimeout(this._packFrameTimeout);
  1160. this._packFrameTimeout = setTimeout(() => {
  1161. this.resumeStream();
  1162. this.globalOptLock = false;
  1163. }, 100);
  1164. } else {
  1165. console.error('补帧有误:', JSON.stringify(frameData));
  1166. }
  1167. }
  1168. },
  1169. );
  1170. }
  1171. }
  1172. handleBreath(request) {
  1173. const npsRes = this.moveService.getBreakPoints(request);
  1174. //this.logger.log('npsRes', npsRes.nps);
  1175. this.streamService.pushNormalDataToStream(npsRes);
  1176. }
  1177. updateStatus(): void {
  1178. const reply = {
  1179. data: { action_type: 1009, echo_msg: { echoMsg: Date.now() } },
  1180. track: false,
  1181. };
  1182. this.streamService.pushNormalDataToStream(reply);
  1183. }
  1184. updateUserStatus(request) {
  1185. try {
  1186. const usersData = this.rotateService.getNewUserStateRequest(request);
  1187. if (usersData) {
  1188. usersData.actionType = 1024;
  1189. //this.logger.log(
  1190. // 'joystick:->updateUserStatus' +
  1191. // 'playerPosition:' +
  1192. // JSON.stringify(
  1193. // redisMeta['newUserStates'][0].playerState.player.position,
  1194. // ),
  1195. // );
  1196. this.streamService.pushNormalDataToStream(usersData);
  1197. } else {
  1198. this.logger.error('updateUserStatus::function-empty');
  1199. }
  1200. } catch (error) {
  1201. this.logger.error('updateUserStatus::function', error.message);
  1202. }
  1203. }
  1204. pushFirstRender(clipPath: string, metaData: string): Promise<boolean> {
  1205. return new Promise<boolean>(async (resolve, reject) => {
  1206. try {
  1207. const streamData: StreamFrameType = {
  1208. frame: 1,
  1209. clipPath: clipPath,
  1210. metaData: metaData,
  1211. serverTime: this.mockserverTime,
  1212. DIR: 1,
  1213. };
  1214. const hasPush = await this.streamService.pushFrameToSteam(streamData);
  1215. return resolve(hasPush.done);
  1216. } catch (error) {
  1217. return reject(false);
  1218. }
  1219. });
  1220. }
  1221. handleStream() {
  1222. this.logger.log('this.frameCntSubscription', this.frameCntSubscription);
  1223. let redisData;
  1224. if (!this.frameCntSubscription) {
  1225. this.frameCntSubscription = this.frameCnt.subscribe(async (frame) => {
  1226. try {
  1227. this.logger.log('frame', frame);
  1228. console.log(
  1229. 'networkState:::--->' +
  1230. ' maxMessageSize: ' +
  1231. this.channel.maxMessageSize() +
  1232. ' bytesReceived: ' +
  1233. this.peer.bytesReceived() +
  1234. ' bytesSent: ' +
  1235. this.peer.bytesSent() +
  1236. ' rtt: ' +
  1237. this.peer.rtt() +
  1238. ' state: ' +
  1239. this.peer.state(),
  1240. );
  1241. if (frame === 1) {
  1242. // redisData = await this.rotateService.echo(this.user_id, true);
  1243. const app_id = this.configService.get('app.appId');
  1244. console.log('首页数据', app_id, this.user_id);
  1245. redisData = this.rotateService.getFirstStreamData(
  1246. app_id,
  1247. this.user_id,
  1248. );
  1249. this.logger.log('获取-首屏', redisData);
  1250. this.onSteaming = true;
  1251. this.holdSteam();
  1252. if (redisData && 'mediaSrc' in redisData) {
  1253. const mediaSrc: string = redisData.mediaSrc || '';
  1254. if (mediaSrc.length > 0) {
  1255. const src = mediaSrc.split('?')[0];
  1256. const clipPath = this.configService.get('app.prefix') + src;
  1257. delete redisData.mediaSrc;
  1258. this.logger.log(
  1259. `user:${this.user_id}:first render stream` +
  1260. JSON.stringify({ path: clipPath, meta: redisData }),
  1261. );
  1262. const status = await this.pushFirstRender(
  1263. clipPath,
  1264. JSON.stringify(redisData),
  1265. );
  1266. if (status) {
  1267. this.firstRender = true;
  1268. this.frameCnt.next(2);
  1269. this.resumeStream();
  1270. } else {
  1271. this.logger.error('first render problem', status);
  1272. }
  1273. }
  1274. } else {
  1275. this.logger.error(`first render problem:${frame}`);
  1276. }
  1277. }
  1278. if (frame > 1) {
  1279. const isOk =
  1280. !this.onMoving.value &&
  1281. !this.onRotating.value &&
  1282. !this.onJoysticking.value &&
  1283. !this.onSteaming &&
  1284. this.firstRender;
  1285. console.log(
  1286. '空白流条件-->:' +
  1287. isOk +
  1288. ' onMoving: ' +
  1289. this.onMoving.value +
  1290. ' onRotating: ' +
  1291. this.onRotating.value +
  1292. ' onJoysticking: ' +
  1293. this.onJoysticking.value +
  1294. ' onSteaming: ' +
  1295. this.onSteaming +
  1296. ' firstRender: ' +
  1297. this.firstRender,
  1298. );
  1299. }
  1300. if (
  1301. frame > 1 &&
  1302. !this.onMoving.value &&
  1303. !this.onRotating.value &&
  1304. !this.onJoysticking.value &&
  1305. !this.onSteaming &&
  1306. this.firstRender
  1307. ) {
  1308. // debugger
  1309. const redisDataAuto = await this.rotateService.echo(
  1310. this.user_id,
  1311. false,
  1312. );
  1313. if (redisDataAuto) {
  1314. this.logger.log(`空白流::有数据:${frame}`);
  1315. 'mediaSrc' in redisDataAuto && delete redisDataAuto.mediaSrc;
  1316. const streamMeta: StreamMetaType = {
  1317. frame: frame,
  1318. metaData: JSON.stringify(redisDataAuto),
  1319. };
  1320. this.streamService.pushMetaDataToSteam(streamMeta);
  1321. } else {
  1322. this.stopStream();
  1323. this.logger.log('空流无Redis数据');
  1324. }
  1325. }
  1326. } catch (error) {
  1327. if (this.frameCnt.getValue() === 1) {
  1328. this.logger.error('首屏读取有误:', redisData, error.message);
  1329. }
  1330. this.stopStream();
  1331. this.logger.error('handleStream', error.message);
  1332. }
  1333. });
  1334. }
  1335. }
  1336. }