scene.service.ts 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423
  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. /**
  501. * 行走动作
  502. *
  503. * @param request
  504. */
  505. async walking(request: MoveRequest) {
  506. this.latestWalkingRequest = request;
  507. this.logger.log('walking-trace_id', request.trace_id);
  508. // if (this.isHasWalkingJoints()) {
  509. // console.log('lock-锁-walking', this.latestWalkingRequest);
  510. // this.globalOptLock = true;
  511. // }
  512. // 进入正常walking流程
  513. if (!this.onMoving.getValue()) {
  514. console.log('walking-step-main-1', request.trace_id);
  515. this.latestWalkingRequest = null;
  516. this.handleWalking(request);
  517. } else {
  518. this.globalOptLock = true;
  519. console.log('lock-锁-walking', this.latestWalkingRequest);
  520. }
  521. this.handleWalkingJoints();
  522. }
  523. /**
  524. * 一段walking每个Joints关节点
  525. * @param request
  526. */
  527. handleWalkingJoints() {
  528. // 每个关节点
  529. if (!this.moveSliceLastFrameSub) {
  530. this.moveSliceLastFrameSub = this.moveSliceLastFrame.subscribe(
  531. async (frame: MovingLastUpdateType) => {
  532. //TODO 正在行走时,有新的reqest
  533. if (frame) {
  534. // console.log('unlock-Joints', JSON.stringify(frame));
  535. this.logger.log('Joints', JSON.stringify(frame));
  536. this.resumeRotate();
  537. let isRotateStop = false;
  538. let isWalkingStop = false;
  539. // 在全局锁的情况下
  540. if (this.globalOptLock) {
  541. isRotateStop = !!this.latestRotateRequest && this.onMoving.value;
  542. isWalkingStop =
  543. !!this.latestWalkingRequest && this.onMoving.value;
  544. console.log('g--isRotateStop', isRotateStop);
  545. console.log('g--isWalkingStop', isWalkingStop);
  546. // 这个就是双暂时出现的时候, 强制只执行一次,以isWalkingStop为主
  547. if (isRotateStop && isWalkingStop) {
  548. isRotateStop = false;
  549. }
  550. console.log('g--1-isRotateStop', isRotateStop);
  551. console.log('g--1-isWalkingStop', isWalkingStop);
  552. // 这个旋转暂停
  553. if (isRotateStop) {
  554. const hasStop = await this.handleRotateOrWalkingStop(
  555. this.latestRotateRequest,
  556. );
  557. console.log('旋转-hasStop', hasStop);
  558. this.clearWalkingJoints();
  559. this.cleanMoveSteam();
  560. this.globalOptLock = false;
  561. }
  562. // 这个行走暂停
  563. if (isWalkingStop) {
  564. const hasStop = await this.handleRotateOrWalkingStop(
  565. this.latestWalkingRequest,
  566. );
  567. console.log('walking-hasStop', hasStop);
  568. this.clearWalkingJoints();
  569. this.cleanMoveSteam();
  570. this.globalOptLock = false;
  571. console.log('unlock-walking');
  572. this.handleReWalking(this.latestWalkingRequest);
  573. // console.log('this', this.rewalking);
  574. }
  575. }
  576. }
  577. },
  578. );
  579. }
  580. }
  581. /**
  582. * 清除所有的节点信信息
  583. * @param request
  584. */
  585. clearWalkingJoints() {
  586. this.moveSliceLastFrame.next(null);
  587. this.lastMovingPointArray = [];
  588. }
  589. /**
  590. * 是否有行走关节点
  591. * @returns boolean
  592. */
  593. isHasWalkingJoints(): boolean {
  594. return this.lastMovingPointArray.length > 0;
  595. }
  596. /**
  597. * 行走队列处理器
  598. * @param request MoveRequest
  599. * @returns void
  600. */
  601. async handleWalking(request: MoveRequest): Promise<void> {
  602. try {
  603. // if (!this.onMoving.getValue()) {
  604. console.log('walking-step-main-2', request.trace_id);
  605. const start = performance.now();
  606. this._rotateCount = 0;
  607. const user = this.moveService.users[this.user_id];
  608. console.log('进入1 - searchRoad');
  609. this.logger.log(
  610. 'handleWalking-users' +
  611. JSON.stringify(this.moveService.users) +
  612. ' this.user_id: ' +
  613. this.user_id,
  614. );
  615. this.logger.log(
  616. 'handleWalking-currentUser' +
  617. JSON.stringify(user) +
  618. ' this.user_id: ' +
  619. this.user_id,
  620. );
  621. console.log('path-start' + user.breakPointId);
  622. const path = await this.getRouterService.searchRoad(
  623. user.appId,
  624. user.breakPointId,
  625. request.clicking_action.clicking_point,
  626. );
  627. this.logger.log('walking-path', path);
  628. if (!path) {
  629. console.log('不存在--path', path);
  630. this.cleanMoveSteam();
  631. this.clearWalkingJoints();
  632. this.resumeRotate();
  633. this.resumeStream();
  634. return;
  635. }
  636. // debugger;
  637. const walkingRes = await this.moveService.move(path, request);
  638. if (walkingRes && (!this.onMoving.value || this.rewalking)) {
  639. // 二维数组 做move 序列, move类型
  640. //console.log('move-walkingRes:' + JSON.stringify(walkingRes));
  641. this.handleStopRotate();
  642. if (walkingRes && walkingRes?.length >= 1) {
  643. for (let i = 0; i <= walkingRes.length - 1; i++) {
  644. Array.from(walkingRes[i]).forEach(
  645. (item: StreamReplyType, index: number) => {
  646. console.log(
  647. '20220628test:handleWalking->' +
  648. item['newUserStates'][0].renderInfo.isMoving,
  649. );
  650. //const IDRflag = index % 5 === 0 ? 1 : 3;
  651. const IDRflag = item.isIDR ? 1 : 3;
  652. const dir = this.isHeaderOrLast(
  653. index,
  654. walkingRes[i].length - 1,
  655. );
  656. item.DIR = dir ? 1 : IDRflag;
  657. //将每段最后一个推入lastMovingPointArray
  658. if (index === walkingRes[i].length - 1) {
  659. this.lastMovingPointArray.push({
  660. mediaSrc: item.mediaSrc,
  661. metaData: item,
  662. });
  663. }
  664. },
  665. );
  666. }
  667. }
  668. // walkingRes marker to everybody
  669. const seqs = Array.from(walkingRes).flat() as any as StreamReplyType[];
  670. if (seqs?.length) {
  671. this.logger.log(
  672. 'walking --队列总览:' +
  673. ' 总段数: ' +
  674. walkingRes.length +
  675. ' 镜头帧数:' +
  676. walkingRes[0].length +
  677. ' 行走段数:' +
  678. (walkingRes[0]?.length
  679. ? walkingRes.length - 1
  680. : walkingRes.length) +
  681. ' 队列总帧数:' +
  682. seqs.length,
  683. );
  684. const stop = performance.now();
  685. const inMillSeconds = stop - start;
  686. const rounded = Number(inMillSeconds).toFixed(3);
  687. this.logger.log(`[timer]-move-入队列前:-->${rounded}ms`);
  688. this.handleSeqMoving(seqs);
  689. } else {
  690. console.error('walking-move无数据');
  691. this.cleanMoveSteam();
  692. this.resumeStream();
  693. }
  694. // }
  695. }
  696. // });
  697. // }
  698. } catch (error) {
  699. this.logger.error('walking', error.message);
  700. this.cleanMoveSteam();
  701. this.resumeStream();
  702. }
  703. }
  704. /**
  705. * 改变路线后的walking队列处理(中转)
  706. * @param request MoveRequest
  707. */
  708. handleReWalking(request: MoveRequest) {
  709. // this.latestWalkingRequest = null;
  710. this.rewalking = true;
  711. this.handleWalking(request);
  712. }
  713. /***
  714. * joystick main core
  715. */
  716. async joystick(request: JoystickRequest) {
  717. // TODO hasJoystickMoveRequest中断
  718. this.logger.log('this.hasJoystickMoveRequest', this.hasJoystickMoveRequest);
  719. if (!this.hasJoystickMoveRequest) {
  720. this.handlejoystick(request);
  721. }
  722. }
  723. /**
  724. * joystick 二合一推流
  725. * @param joystickRes StreamMetaType | StreamFrameType;
  726. */
  727. handlePushJoyStickSteamSeq = seqExeAsyncFn(this.handlePushJoyStickSteam);
  728. async handlePushJoyStickSteam(joystickRes: StreamReplyType) {
  729. this.holdSteam();
  730. this.globalOptLock = true;
  731. //console.log('joystickRes有mediaSrc', joystickRes.mediaSrc);
  732. console.log(
  733. 'handlejoystick-angle->相机角度-------------------------:' +
  734. joystickRes['newUserStates'][0].playerState.camera.angle.yaw,
  735. );
  736. let streamData: StreamFrameType | StreamMetaType;
  737. this.joystickFrameCnt = this.frameCnt.getValue() + 1;
  738. const hasMedia = joystickRes?.mediaSrc && joystickRes?.mediaSrc.length > 0;
  739. if (hasMedia) {
  740. const src = joystickRes.mediaSrc.split('?')[0];
  741. const mediaSrc = this.configService.get('app.prefix') + src;
  742. // IDR flag设置为I帧
  743. const setDIR = joystickRes.isIDR ? 1 : 3;
  744. streamData = {
  745. frame: this.joystickFrameCnt,
  746. clipPath: mediaSrc,
  747. metaData: JSON.stringify(joystickRes),
  748. serverTime: this.mockserverTime,
  749. DIR: setDIR,
  750. };
  751. console.log(
  752. 'handlejoystick-hasMedia->-------------------------:' +
  753. ' frame: ' +
  754. streamData.frame +
  755. mediaSrc +
  756. ' IDR :' +
  757. setDIR,
  758. );
  759. } else {
  760. streamData = {
  761. frame: this.joystickFrameCnt,
  762. metaData: JSON.stringify(joystickRes),
  763. };
  764. }
  765. console.log(
  766. '20220627test-complementFrame 进行1' + '***' + streamData.frame,
  767. );
  768. // 过滤新东西, 推完给回false
  769. this.moveService.sendingFrameForJoystick = true;
  770. const hasPush = hasMedia
  771. ? await this.streamService.pushFrameToSteam(streamData as StreamFrameType)
  772. : await this.streamService.pushMetaDataToSteam(
  773. streamData as StreamMetaType,
  774. );
  775. if (hasPush.done) {
  776. this.isJoystickHasStream = true;
  777. console.log('joystick-hasPush', hasPush);
  778. // if (this.isJoystickHasStream) {
  779. // await this.sleep(20);
  780. // }
  781. // await this.sleep(20);
  782. this.frameCnt.next(hasPush.frame);
  783. this.moveService.sendingFrameForJoystick = false;
  784. const data = joystickRes as StreamReplyType;
  785. console.log('handlejoystick-isIDR:' + data.isIDR);
  786. // if (data?.moveOver && data.moveOver) {
  787. // // moveOver
  788. // console.log('回传updateUser', data);
  789. // // const userId = this.user_id;
  790. // // 回传点暂时有问题,待修复
  791. // //const breakPointId = data.endBreakPointId || data.breakPointId;
  792. // //const lastReply = JSON.stringify(joystickRes);
  793. // //this.moveService.updateUser(userId, breakPointId, lastReply);
  794. // }
  795. /**
  796. * 这个complementFrame 具体说明 pools 是complementFrame这个返回值
  797. * 1. 第一次要在200ms后调用, 如有值(pools) 就要返回主流程执行,但设置hasJoystickFocusRepeat为true
  798. * 2. 第二次或N进入在hasJoystickFocusRepeat为true并绕过200ms timeout,如pools有值返回(2)主流程直到pools为null
  799. * 3. 如pools为空走回 200ms流程 (这时pools应该为空),交权回空流。
  800. */
  801. if (this.hasJoystickFocusRepeat) {
  802. const complementFrame = this.moveService.complementFrame(
  803. this.user_id,
  804. ) as StreamReplyType;
  805. if (complementFrame) {
  806. console.log(
  807. '20220627test-complementFrame 进行' +
  808. complementFrame.mediaSrc +
  809. '***' +
  810. this.frameCnt.value,
  811. );
  812. // 第二次或N次进入时如果有值直接重新进入流主程
  813. this.holdSteam();
  814. this.handlePushJoyStickSteamSeq(complementFrame);
  815. this.globalOptLock = true;
  816. } else {
  817. console.log('20220627test-complementFrame 结束');
  818. // 第二次或N次无pool数据再次trigger handleJoystickStop
  819. this.hasJoystickFocusRepeat = false;
  820. this.testTimer = 0;
  821. //this.handleJoystickStop(hasPush);
  822. this.globalOptLock = false;
  823. this.resumeStream();
  824. }
  825. } else {
  826. this.handleJoystickStop(hasPush);
  827. }
  828. } else {
  829. console.error('joystick-流地址有误::', joystickRes.mediaSrc);
  830. this.logger.error('joystick-流地址有误::', joystickRes.mediaSrc);
  831. this.resumeStream();
  832. }
  833. }
  834. /**
  835. * Joystick Stop function
  836. */
  837. handleJoystickStop(hasPush: StreamPushResponse) {
  838. // 最后一帧200ms
  839. clearTimeout(this._JoyStickingSteamTimeout);
  840. this._JoyStickingSteamTimeout = setTimeout(async () => {
  841. console.log('20220627test-complementFrame handleJoystickStop 200ms之后');
  842. const complementFrame = this.moveService.complementFrame(
  843. this.user_id,
  844. ) as StreamReplyType;
  845. // console.log('has-complementFrame', complementFrame);
  846. console.log('gemer-test-complementFrame', complementFrame);
  847. if (complementFrame) {
  848. this.hasJoystickFocusRepeat = true;
  849. this.globalOptLock = true;
  850. this.testTimer += 1;
  851. console.log('complementFrame-有值');
  852. const start = performance.now();
  853. this.handlePushJoyStickSteamSeq(complementFrame);
  854. const stop = performance.now();
  855. console.log('handlePushJoyStickSteam', this.testTimer);
  856. const inMillSeconds = stop - start;
  857. const rounded = Number(inMillSeconds).toFixed(3);
  858. console.log(`complementFrame调用时间---->${rounded}`);
  859. } else {
  860. console.log('complementFrame-空1');
  861. this.logger.log('joystick opt done');
  862. this.logger.log('joystick 交权给空流,当前pts', hasPush.frame);
  863. this.hasJoystickFocusRepeat = false;
  864. this.onJoysticking.next(false);
  865. this.resumeStream();
  866. this.joystickFrameCnt = -1;
  867. this.isJoystickHasStream = false;
  868. }
  869. }, 200);
  870. }
  871. /***
  872. * joystick
  873. */
  874. async handlejoystick(request: JoystickRequest) {
  875. try {
  876. //const joystickRes = await this.moveService.joystick(request);
  877. this._rotateCount = 0;
  878. const joystickRes = await this.moveService.seqExeJoystick(request);
  879. this.logger.log(
  880. 'joystick-breakPointId:' +
  881. this.moveService.users[this.user_id].breakPointId,
  882. );
  883. // 有数据 [0]是rotate数据,[1-infinity]是walking数据
  884. //this.logger.log('joystickRes', JSON.stringify(joystickRes));
  885. if (joystickRes) {
  886. this.onJoysticking.next(true);
  887. // console.log(
  888. // 'handlejoysticktesttest:' +
  889. // joystickRes.mediaSrc +
  890. // ',相机坐标:' +
  891. // JSON.stringify(
  892. // joystickRes.newUserStates[0].playerState.player.position,
  893. // ),
  894. // );
  895. if (!this.onMoving.getValue()) {
  896. console.log('handlejoystick:data', JSON.stringify(joystickRes));
  897. this.handlePushJoyStickSteamSeq(joystickRes);
  898. }
  899. } else {
  900. console.log('handlejoystick:null');
  901. this.onJoysticking.next(false);
  902. }
  903. } catch (error) {
  904. console.error('joystick错误', error);
  905. this.onJoysticking.next(false);
  906. this.logger.error('joystick', error.message);
  907. }
  908. }
  909. /**
  910. * 主要处理moving的序列动作
  911. * @param seqs StreamReplyType[]
  912. */
  913. handleSeqMoving(seqs: StreamReplyType[]) {
  914. // if (!this.moveQueueSubscription) {
  915. // this.handleMoveSteam();
  916. // }
  917. // this.logger.log('moving-seqs', seqs.length);
  918. this.onMoving.next(true);
  919. this.holdSteam();
  920. // 保证每一段都是序列动作的前面队列是空的
  921. // this.moveQueue.clean();
  922. seqs.forEach((frame: StreamReplyType) => {
  923. const mediaSrc = frame.mediaSrc;
  924. const src = mediaSrc.split('?')[0];
  925. const clipPath = this.configService.get('app.prefix') + src;
  926. const type = frame.mType?.length ? frame.mType.slice() : 'move';
  927. const stream: StreamFrameType = {
  928. frame: -1,
  929. clipPath: clipPath,
  930. metaData: JSON.stringify(frame),
  931. serverTime: this.mockserverTime,
  932. DIR: frame.DIR,
  933. mType: type,
  934. };
  935. // this.moveQueue.next(stream);
  936. this.handleMoveSteam(stream);
  937. });
  938. }
  939. handleMoveSteam = seqExeAsyncFn(this.handleMoveSteamFn);
  940. async handleMoveSteamFn(stream: StreamFrameType) {
  941. try {
  942. if (!this.isStopJointing) {
  943. const metaData: StreamReplyType = JSON.parse(stream.metaData);
  944. // if (this.moveframeCnt === -1) {
  945. // this.moveframeCnt = this.frameCnt.getValue();
  946. // }
  947. // this.moveframeCnt += 1;
  948. // this.latestBreakPointId = metaData.endBreakPointId;
  949. this.moveframeCnt = this.frameCnt.value + 1;
  950. const streamData: StreamFrameType = {
  951. frame: this.moveframeCnt,
  952. clipPath: stream.clipPath,
  953. metaData: stream.metaData,
  954. serverTime: this.mockserverTime,
  955. DIR: stream.DIR,
  956. };
  957. this.logger.log(
  958. '[media-move]: ' +
  959. ', moveframeCnt: ' +
  960. this.moveframeCnt +
  961. ', clipPath: ' +
  962. stream.clipPath +
  963. ', mType: ' +
  964. stream.mType +
  965. ', DIR: ' +
  966. stream.DIR,
  967. // stream.metaData,
  968. );
  969. this.logger.log(
  970. '[media-move-lastMovingPointArray]',
  971. this.lastMovingPointArray?.length,
  972. );
  973. // 记录lastMoveStreamFrame给打断逻辑使用
  974. this.lastMoveStreamFrame.next(streamData);
  975. // this.lastMoveStreamFrameBk = streamData;
  976. this.holdSteam();
  977. // this.globalOptLock = true;
  978. //console.log('20220627test:handleMoveSteam:' + stream.clipPath)
  979. const frameTimeStart = performance.now();
  980. const res = await this.streamService.pushFrameToSteam(streamData);
  981. const isLastFrameIndex = this.lastMovingPointArray.findIndex(
  982. (item) => item.mediaSrc === metaData.mediaSrc,
  983. );
  984. // this.logger.log('path-update-index', isLastFrameIndex);
  985. if (res.done) {
  986. const frameTimeEnd = performance.now();
  987. const frameAverage = frameTimeEnd - frameTimeStart;
  988. console.log('walking-frameAverage', frameAverage);
  989. await this.sleep(40);
  990. this.frameCnt.next(res.frame);
  991. //关节点入库
  992. if (isLastFrameIndex > -1) {
  993. //this.logger.log('path-update-array', this.lastMovingPointArray);
  994. const currentMeta = this.lastMovingPointArray[isLastFrameIndex];
  995. const userId = this.user_id;
  996. const breakPointId = currentMeta.metaData.endBreakPointId;
  997. const lastReply = currentMeta.metaData;
  998. this.moveService.updateUser(userId, breakPointId, lastReply);
  999. this.lastMovingPointArray.splice(isLastFrameIndex, 1);
  1000. this.moveSliceLastFrame.next(currentMeta);
  1001. }
  1002. clearTimeout(this._moveTimeout);
  1003. this._moveTimeout = setTimeout(() => {
  1004. this.logger.log('move 交权给空流,当前pts', res.frame);
  1005. this.rewalking = false;
  1006. this.frameCnt.next(res.frame);
  1007. this.rotateframeCnt = -1;
  1008. this.onMoving.next(false);
  1009. this.onJoysticking.next(false);
  1010. this.lastMovingPointArray = [];
  1011. this.hasJoystickMoveRequest = false;
  1012. this.cleanMoveSteam();
  1013. this.globalOptLock = false;
  1014. this.resumeStream();
  1015. this.logger.log('move end');
  1016. }, 200);
  1017. } else {
  1018. console.error('流地址有误::', res.frame, JSON.stringify(res));
  1019. this.logger.error(
  1020. `movesteam::当前帧:${res.frame}` + JSON.stringify(res),
  1021. );
  1022. this.resumeStream();
  1023. }
  1024. }
  1025. } catch (error) {
  1026. this.logger.error('handleMoveSteam::error', error);
  1027. }
  1028. }
  1029. cleanMoveSteam() {
  1030. this.moveQueue.clean();
  1031. if (this.moveQueueSubscription) {
  1032. this.moveQueueSubscription.unsubscribe();
  1033. this.moveQueueSubscription = null;
  1034. }
  1035. if (this.walkingSub) {
  1036. this.walkingSub.unsubscribe();
  1037. this.walkingSub = null;
  1038. }
  1039. if (this.moveSliceLastFrameSub) {
  1040. this.lastMoveStreamFrame.next(null);
  1041. this.moveSliceLastFrameSub.unsubscribe();
  1042. this.moveSliceLastFrameSub = null;
  1043. }
  1044. // if (this.clickQueueSub) {
  1045. // this.clickQueueSub.unsubscribe();
  1046. // this.clickQueueSub = null;
  1047. // }
  1048. this.rotateStopThrottle = false;
  1049. }
  1050. handleDataChanelOpen(channel: DataChannel, peer: PeerConnection): void {
  1051. this.channel = channel;
  1052. this.peer = peer;
  1053. this.streamService.setChannel(channel);
  1054. this.startSteaming.next(true);
  1055. // this.startStream();
  1056. // this.handleStream();
  1057. this.channel.onBufferedAmountLow(() => {
  1058. console.error('onBufferedAmountLow-rtt', this.peer.rtt());
  1059. console.error('onBufferedAmountLow', this.channel.bufferedAmount());
  1060. //64k->65536 128k->131072
  1061. this.channel.setBufferedAmountLowThreshold(262144);
  1062. this.logger.error('onBufferedAmountLow', this.channel.bufferedAmount());
  1063. });
  1064. }
  1065. handleDataChanelClose(): void {
  1066. this.stopStream();
  1067. this.startSteaming.next(false);
  1068. this.streamService.closeChannel();
  1069. this.cleanMoveSteam();
  1070. // const exitRequest: ExitRequest = {
  1071. // action_type: 1002,
  1072. // user_id: this.user_id,
  1073. // trace_id: '',
  1074. // };
  1075. this.exit();
  1076. }
  1077. handleMessage(message: string | Buffer) {
  1078. try {
  1079. if (typeof message === 'string') {
  1080. // wasm:特例, requestIframe
  1081. if (message.includes('wasm:')) {
  1082. const parseData = message
  1083. ? String(message).replace('wasm:', '')
  1084. : `{"MstType":1}`;
  1085. const msg: RTCMessageRequest = JSON.parse(parseData);
  1086. this.logger.error('lostIframe-message', JSON.stringify(msg));
  1087. if (Number(msg.MstType) === 0) {
  1088. this.handleIframeRequest();
  1089. }
  1090. } else {
  1091. const msg: RTCMessageRequest = JSON.parse(message);
  1092. // console.log('msg.action_type:' + msg.action_type);
  1093. switch (msg.action_type) {
  1094. case ActionType.walk:
  1095. const walk = msg as any as MoveRequest;
  1096. this.walking(walk);
  1097. break;
  1098. case ActionType.joystick:
  1099. const JoystickRequest = msg as any as JoystickRequest;
  1100. this.joystick(JoystickRequest);
  1101. break;
  1102. case ActionType.breathPoint:
  1103. this.handleBreath(msg);
  1104. break;
  1105. case ActionType.rotate:
  1106. const rotateRequest: RotateRequest = msg;
  1107. this.rotate(rotateRequest);
  1108. break;
  1109. case ActionType.userStatus:
  1110. this.updateUserStatus(msg);
  1111. break;
  1112. case ActionType.status:
  1113. this.updateStatus();
  1114. break;
  1115. default:
  1116. break;
  1117. }
  1118. }
  1119. }
  1120. } catch (error) {
  1121. this.logger.error('handleMessage:rtc--error', error.message);
  1122. }
  1123. }
  1124. async handleIframeRequest() {
  1125. //TODO Iframe 最终传什么?
  1126. this.holdSteam();
  1127. this.requestIFrameQueue.next(this.streamService.lastStreamFrame.getValue());
  1128. if (!this.requestIFrameQueueSub) {
  1129. this.requestIFrameQueueSub = this.requestIFrameQueue.subscribe(
  1130. async (frameData: StreamFrameType) => {
  1131. if (frameData) {
  1132. this.globalOptLock = true;
  1133. const nextFrame = this.frameCnt.getValue() + 1;
  1134. this.logger.warn('lostIframe', nextFrame);
  1135. frameData.frame = nextFrame;
  1136. frameData.DIR = 1;
  1137. const res = await this.streamService.pushFrameToSteam(frameData);
  1138. if (res.done) {
  1139. this.logger.error(
  1140. ' frame:' + res.frame + ' 补帧::' + JSON.stringify(frameData),
  1141. );
  1142. this.frameCnt.next(res.frame);
  1143. clearTimeout(this._packFrameTimeout);
  1144. this._packFrameTimeout = setTimeout(() => {
  1145. this.resumeStream();
  1146. this.globalOptLock = false;
  1147. }, 100);
  1148. } else {
  1149. console.error('补帧有误:', JSON.stringify(frameData));
  1150. }
  1151. }
  1152. },
  1153. );
  1154. }
  1155. }
  1156. handleBreath(request) {
  1157. const npsRes = this.moveService.getBreakPoints(request);
  1158. //this.logger.log('npsRes', npsRes.nps);
  1159. this.streamService.pushNormalDataToStream(npsRes);
  1160. }
  1161. updateStatus(): void {
  1162. const reply = {
  1163. data: { action_type: 1009, echo_msg: { echoMsg: Date.now() } },
  1164. track: false,
  1165. };
  1166. this.streamService.pushNormalDataToStream(reply);
  1167. }
  1168. updateUserStatus(request) {
  1169. try {
  1170. const usersData = this.rotateService.getNewUserStateRequest(request);
  1171. if (usersData) {
  1172. usersData.actionType = 1024;
  1173. //this.logger.log(
  1174. // 'joystick:->updateUserStatus' +
  1175. // 'playerPosition:' +
  1176. // JSON.stringify(
  1177. // redisMeta['newUserStates'][0].playerState.player.position,
  1178. // ),
  1179. // );
  1180. this.streamService.pushNormalDataToStream(usersData);
  1181. } else {
  1182. this.logger.error('updateUserStatus::function-empty');
  1183. }
  1184. } catch (error) {
  1185. this.logger.error('updateUserStatus::function', error.message);
  1186. }
  1187. }
  1188. pushFirstRender(clipPath: string, metaData: string): Promise<boolean> {
  1189. return new Promise<boolean>(async (resolve, reject) => {
  1190. try {
  1191. const streamData: StreamFrameType = {
  1192. frame: 1,
  1193. clipPath: clipPath,
  1194. metaData: metaData,
  1195. serverTime: this.mockserverTime,
  1196. DIR: 1,
  1197. };
  1198. const hasPush = await this.streamService.pushFrameToSteam(streamData);
  1199. return resolve(hasPush.done);
  1200. } catch (error) {
  1201. return reject(false);
  1202. }
  1203. });
  1204. }
  1205. handleStream() {
  1206. this.logger.log('this.frameCntSubscription', this.frameCntSubscription);
  1207. let redisData;
  1208. if (!this.frameCntSubscription) {
  1209. this.frameCntSubscription = this.frameCnt.subscribe(async (frame) => {
  1210. try {
  1211. this.logger.log('frame', frame);
  1212. console.log(
  1213. 'networkState:::--->' +
  1214. ' maxMessageSize: ' +
  1215. this.channel.maxMessageSize() +
  1216. ' bytesReceived: ' +
  1217. this.peer.bytesReceived() +
  1218. ' bytesSent: ' +
  1219. this.peer.bytesSent() +
  1220. ' rtt: ' +
  1221. this.peer.rtt() +
  1222. ' state: ' +
  1223. this.peer.state(),
  1224. );
  1225. if (frame === 1) {
  1226. // redisData = await this.rotateService.echo(this.user_id, true);
  1227. const app_id = this.configService.get('app.appId');
  1228. console.log('首页数据', app_id, this.user_id);
  1229. redisData = this.rotateService.getFirstStreamData(
  1230. app_id,
  1231. this.user_id,
  1232. );
  1233. this.logger.log('获取-首屏', redisData);
  1234. this.onSteaming = true;
  1235. this.holdSteam();
  1236. if (redisData && 'mediaSrc' in redisData) {
  1237. const mediaSrc: string = redisData.mediaSrc || '';
  1238. if (mediaSrc.length > 0) {
  1239. const src = mediaSrc.split('?')[0];
  1240. const clipPath = this.configService.get('app.prefix') + src;
  1241. delete redisData.mediaSrc;
  1242. this.logger.log(
  1243. `user:${this.user_id}:first render stream` +
  1244. JSON.stringify({ path: clipPath, meta: redisData }),
  1245. );
  1246. const status = await this.pushFirstRender(
  1247. clipPath,
  1248. JSON.stringify(redisData),
  1249. );
  1250. if (status) {
  1251. this.firstRender = true;
  1252. this.frameCnt.next(2);
  1253. this.resumeStream();
  1254. } else {
  1255. this.logger.error('first render problem', status);
  1256. }
  1257. }
  1258. } else {
  1259. this.logger.error(`first render problem:${frame}`);
  1260. }
  1261. }
  1262. if (frame > 1) {
  1263. const isOk =
  1264. !this.onMoving.value &&
  1265. !this.onRotating.value &&
  1266. !this.onJoysticking.value &&
  1267. !this.onSteaming &&
  1268. this.firstRender;
  1269. console.log(
  1270. '空白流条件-->:' +
  1271. isOk +
  1272. ' onMoving: ' +
  1273. this.onMoving.value +
  1274. ' onRotating: ' +
  1275. this.onRotating.value +
  1276. ' onJoysticking: ' +
  1277. this.onJoysticking.value +
  1278. ' onSteaming: ' +
  1279. this.onSteaming +
  1280. ' firstRender: ' +
  1281. this.firstRender,
  1282. );
  1283. }
  1284. if (
  1285. frame > 1 &&
  1286. !this.onMoving.value &&
  1287. !this.onRotating.value &&
  1288. !this.onJoysticking.value &&
  1289. !this.onSteaming &&
  1290. this.firstRender
  1291. ) {
  1292. // debugger
  1293. const redisDataAuto = await this.rotateService.echo(
  1294. this.user_id,
  1295. false,
  1296. );
  1297. if (redisDataAuto) {
  1298. this.logger.log(`空白流::有数据:${frame}`);
  1299. 'mediaSrc' in redisDataAuto && delete redisDataAuto.mediaSrc;
  1300. const streamMeta: StreamMetaType = {
  1301. frame: frame,
  1302. metaData: JSON.stringify(redisDataAuto),
  1303. };
  1304. this.streamService.pushMetaDataToSteam(streamMeta);
  1305. } else {
  1306. this.stopStream();
  1307. this.logger.log('空流无Redis数据');
  1308. }
  1309. }
  1310. } catch (error) {
  1311. if (this.frameCnt.getValue() === 1) {
  1312. this.logger.error('首屏读取有误:', redisData, error.message);
  1313. }
  1314. this.stopStream();
  1315. this.logger.error('handleStream', error.message);
  1316. }
  1317. });
  1318. }
  1319. }
  1320. }