gemercheung 3 years ago
parent
commit
8ee4f28922
100 changed files with 569 additions and 117 deletions
  1. 1 3
      src/app.module.ts
  2. 6 2
      src/meta.gateway.ts
  3. 357 0
      src/move/move.service.ts
  4. 1 1
      src/rotate/rotate.service.ts
  5. 2 0
      src/scene/scene.module.ts
  6. 129 110
      src/scene/scene.service.ts
  7. 72 0
      src/scene/stream/stream.d.ts
  8. 1 1
      src/scene/stream/stream.service.ts
  9. BIN
      ws/video/earth/0
  10. BIN
      ws/video/earth/1
  11. BIN
      ws/video/earth/10
  12. BIN
      ws/video/earth/100
  13. BIN
      ws/video/earth/101
  14. BIN
      ws/video/earth/102
  15. BIN
      ws/video/earth/103
  16. BIN
      ws/video/earth/104
  17. BIN
      ws/video/earth/105
  18. BIN
      ws/video/earth/106
  19. BIN
      ws/video/earth/107
  20. BIN
      ws/video/earth/108
  21. BIN
      ws/video/earth/109
  22. BIN
      ws/video/earth/11
  23. BIN
      ws/video/earth/110
  24. BIN
      ws/video/earth/111
  25. BIN
      ws/video/earth/112
  26. BIN
      ws/video/earth/113
  27. BIN
      ws/video/earth/114
  28. BIN
      ws/video/earth/115
  29. BIN
      ws/video/earth/116
  30. BIN
      ws/video/earth/117
  31. BIN
      ws/video/earth/118
  32. BIN
      ws/video/earth/119
  33. BIN
      ws/video/earth/12
  34. BIN
      ws/video/earth/120
  35. BIN
      ws/video/earth/121
  36. BIN
      ws/video/earth/122
  37. BIN
      ws/video/earth/123
  38. BIN
      ws/video/earth/124
  39. BIN
      ws/video/earth/125
  40. BIN
      ws/video/earth/126
  41. BIN
      ws/video/earth/127
  42. BIN
      ws/video/earth/128
  43. BIN
      ws/video/earth/129
  44. BIN
      ws/video/earth/13
  45. BIN
      ws/video/earth/130
  46. BIN
      ws/video/earth/131
  47. BIN
      ws/video/earth/132
  48. BIN
      ws/video/earth/133
  49. BIN
      ws/video/earth/134
  50. BIN
      ws/video/earth/135
  51. BIN
      ws/video/earth/136
  52. BIN
      ws/video/earth/137
  53. BIN
      ws/video/earth/138
  54. BIN
      ws/video/earth/139
  55. BIN
      ws/video/earth/14
  56. BIN
      ws/video/earth/140
  57. BIN
      ws/video/earth/141
  58. BIN
      ws/video/earth/142
  59. BIN
      ws/video/earth/143
  60. BIN
      ws/video/earth/144
  61. BIN
      ws/video/earth/145
  62. BIN
      ws/video/earth/146
  63. BIN
      ws/video/earth/147
  64. BIN
      ws/video/earth/148
  65. BIN
      ws/video/earth/149
  66. BIN
      ws/video/earth/15
  67. BIN
      ws/video/earth/150
  68. BIN
      ws/video/earth/151
  69. BIN
      ws/video/earth/152
  70. BIN
      ws/video/earth/153
  71. BIN
      ws/video/earth/154
  72. BIN
      ws/video/earth/155
  73. BIN
      ws/video/earth/156
  74. BIN
      ws/video/earth/157
  75. BIN
      ws/video/earth/158
  76. BIN
      ws/video/earth/159
  77. BIN
      ws/video/earth/16
  78. BIN
      ws/video/earth/160
  79. BIN
      ws/video/earth/161
  80. BIN
      ws/video/earth/162
  81. BIN
      ws/video/earth/163
  82. BIN
      ws/video/earth/164
  83. BIN
      ws/video/earth/165
  84. BIN
      ws/video/earth/166
  85. BIN
      ws/video/earth/167
  86. BIN
      ws/video/earth/168
  87. BIN
      ws/video/earth/169
  88. BIN
      ws/video/earth/17
  89. BIN
      ws/video/earth/170
  90. BIN
      ws/video/earth/171
  91. BIN
      ws/video/earth/172
  92. BIN
      ws/video/earth/173
  93. BIN
      ws/video/earth/174
  94. BIN
      ws/video/earth/175
  95. BIN
      ws/video/earth/176
  96. BIN
      ws/video/earth/177
  97. BIN
      ws/video/earth/178
  98. BIN
      ws/video/earth/179
  99. BIN
      ws/video/earth/18
  100. 0 0
      ws/video/earth/180

+ 1 - 3
src/app.module.ts

@@ -8,8 +8,6 @@ import { SceneModule } from './scene/scene.module';
 // import { CacheModule } from './cache/cache.module';
 import configuration from './config/configuration';
 import { BullModule } from '@nestjs/bull';
-import { RotateService } from './rotate/rotate.service';
-
 @Module({
   imports: [
     ConfigModule.forRoot({ isGlobal: true, load: [configuration] }),
@@ -21,6 +19,6 @@ import { RotateService } from './rotate/rotate.service';
     // CacheModule,
   ],
   controllers: [AppController],
-  providers: [AppService, MetaGateway, RotateService],
+  providers: [AppService, MetaGateway],
 })
 export class AppModule {}

+ 6 - 2
src/meta.gateway.ts

@@ -203,7 +203,9 @@ export class MetaGateway
       this.sceneService.handleDataChanelClose();
       this.stopSendWertcHeartPack();
       cleanup();
-      this.startstreamingSub & this.startstreamingSub.unsubscribe();
+      if (this.startstreamingSub) {
+        this.startstreamingSub.unsubscribe();
+      }
     });
     this.gameChanel.onMessage((event) => {
       this.sceneService.handleMessage(event);
@@ -317,7 +319,9 @@ export class MetaGateway
   handleDisconnect(client: WebSocket) {
     this.logger.log(`Client disconnected: ${client.id}`);
     this.peer && this.peer.close();
-    this.startstreamingSub & this.startstreamingSub.unsubscribe();
+    if (this.startstreamingSub) {
+      this.startstreamingSub.unsubscribe();
+    }
     this.sceneService.stopStream();
   }
 }

+ 357 - 0
src/move/move.service.ts

@@ -0,0 +1,357 @@
+import { Injectable } from '@nestjs/common';
+import { CacheService } from 'src/cache/cache.service';
+
+@Injectable()
+export class MoveService {
+  constructor(private cacheService: CacheService) {}
+  private Actions = {
+    Clicking: 1,
+    Rotation: 1014,
+    Joystick: 15,
+  };
+  private users = {};
+
+  private reply = {
+    traceIds: [],
+    vehicle: null,
+    mediaSrc: null,
+    newUserStates: [
+      {
+        userId: 'dcff36ae4fc1d',
+        playerState: {
+          roomTypeId: '',
+          person: 0,
+          avatarId: '',
+          skinId: '',
+          roomId: '',
+          isHost: false,
+          isFollowHost: false,
+          skinDataVersion: '',
+          avatarComponents: '',
+          nickName: '',
+          movingMode: 0,
+          attitude: '',
+          areaName: '',
+          pathName: '',
+          pathId: '',
+          avatarSize: 1,
+          extra: '',
+          prioritySync: false,
+          player: {
+            position: { x: -700, y: 0, z: 0 },
+            angle: {
+              pitch: 0,
+              yaw: 0,
+              roll: 0,
+            },
+          },
+          camera: {
+            position: { x: -1145, y: 0, z: 160 },
+            angle: {
+              pitch: 0,
+              yaw: 0,
+              roll: 0,
+            },
+          },
+          cameraCenter: { x: -700, y: 0, z: 0 },
+        },
+        renderInfo: {
+          renderType: 0,
+          videoFrame: null,
+          cameraStateType: 3,
+          isMoving: 1,
+          needIfr: 0,
+          isVideo: 0,
+          stillFrame: 0,
+          isRotating: 0,
+          isFollowing: 0,
+          clientPanoTitlesBitmap: [],
+          clientPanoTreceId: '',
+          prefetchVideoId: '',
+          noMedia: false,
+        },
+        event: null,
+        relation: 1,
+      },
+    ],
+    actionResponses: [
+      {
+        actionType: 1,
+        pointType: 100,
+        extra: '',
+        traceId: '',
+        packetId: '',
+        nps: [],
+        peopleNum: 0,
+        zoneId: '',
+        echoMsg: '',
+        reserveDetail: null,
+        userWithAvatarList: [],
+        newUserStates: [],
+        code: 0,
+        msg: '',
+      },
+    ],
+    getStateType: 0,
+    code: 0,
+    msg: 'OK',
+  };
+
+  init(app_id, userId) {
+    const user = {
+      appId: null,
+      userId: null,
+      breakPointId: null,
+      roomId: null,
+      player: {
+        position: { x: -700, y: 0, z: 0 },
+        angle: {
+          pitch: 0,
+          yaw: 0,
+          roll: 0,
+        },
+      },
+      camera: {
+        position: { x: -1145, y: 0, z: 160 },
+        angle: {
+          pitch: 0,
+          yaw: 0,
+          roll: 0,
+        },
+      },
+      rotateInfo: {
+        frameIndex: 0,
+        horizontal_move: 0,
+        mediaSrc: null,
+      },
+      moveInfo: {},
+      // traceIds: [],
+      // actionResponses:[]
+    };
+
+    user.appId = app_id;
+    user.userId = userId;
+    user.breakPointId = 100;
+    this.users[userId] = user;
+  }
+
+  async move(actionRequest) {
+    try {
+      const userId = actionRequest['user_id'];
+      const traceId = actionRequest['trace_id'];
+      const actionType = actionRequest['action_type'];
+      const user = this.users[userId];
+
+      const appId = user.appId;
+      const path = [100, 101, 102]; //需要计算路径
+      const angle = user.camera.angle.yaw % 45; //纠正需要
+      const index = Math.round(user.camera.angle.yaw / 45); //过渡需要
+
+      const replys = {};
+      const traceIds = [];
+      traceIds.push(traceId);
+
+      //纠正,旋转传到缓存里
+      const checkReplys = [];
+      for (let i = 0; i < angle; ++i) {
+        //let reply = rotateService.rotateForAngle(userId,(angle+i)%359);
+        //reply.traceIds = [];
+        //reply.traceIds.push(traceId);
+        //let actionResponse = rotateService.createActionResponse(actionType,trace_id);
+        //reply.actionResponses = [];
+        //reply.actionResponses.push(actionResponse);
+        //checkReplys.push(reply);
+      }
+      replys['P' + user.breakPointId + 'T' + user.breakPointId] = checkReplys;
+      //replys.push(checkReplys);
+
+      //过渡传到缓存里
+      this.reply.traceIds = traceIds;
+      this.reply['newUserStates'][0].userId = userId;
+      this.reply['actionResponses'][0].traceId = traceId;
+
+      for (let i = 0; i < path.length - 1; ++i) {
+        let pathReplys = [];
+        const start_break_point_id = path[i];
+        const end_break_point_id = path[i + 1];
+        //读redis里的数据,按照frame_index的大小排序
+        const key =
+          'moveframe:app_id:' +
+          appId +
+          ':start_break_point_id:' +
+          start_break_point_id +
+          ':end_break_point_id:' +
+          end_break_point_id +
+          ':angle:' +
+          index;
+        const moveFramesRes = await this.cacheService.get(key);
+        if (moveFramesRes == null) {
+          return replys;
+        }
+        const moveFrames = JSON.parse(moveFramesRes);
+        //读redis里的数据
+        const startBreakPointRes = await this.cacheService.get(
+          'breakpoints:app_id:' +
+            appId +
+            ':break_point_id:' +
+            start_break_point_id,
+        );
+
+        const startBreakPoint = JSON.parse(startBreakPointRes);
+
+        const endBreakPointRes = await this.cacheService.get(
+          'breakpoints:app_id:' +
+            appId +
+            ':break_point_id:' +
+            end_break_point_id,
+        );
+        const endBreakPoint = JSON.parse(endBreakPointRes);
+        pathReplys = this.createCacheReplys(
+          moveFrames,
+          traceId,
+          userId,
+          start_break_point_id,
+          startBreakPoint.position,
+          endBreakPoint.position,
+        );
+        //replys.push(pathReplys);
+        replys['P' + start_break_point_id + 'T' + end_break_point_id] =
+          pathReplys;
+      }
+      return replys;
+    } catch (error) {
+      console.log('MoveService', error);
+    }
+  }
+
+  createCacheReplys(
+    moveFrames,
+    traceId,
+    userId,
+    breakPointId,
+    startPosition,
+    endPosition,
+  ) {
+    const replys = [];
+
+    const angle =
+      -1 *
+      this.getAngle(
+        startPosition,
+        {
+          x: startPosition.x + 1,
+          y: startPosition.y,
+        },
+        endPosition,
+      );
+
+    for (let i = 1; i < moveFrames.length; i += 5) {
+      const moveFrame = moveFrames[i];
+
+      const reply = JSON.parse(JSON.stringify(this.reply));
+      reply.traceIds.push(traceId);
+      reply['newUserStates'][0].userId = userId;
+
+      reply['newUserStates'][0].playerState.player.position = {
+        x:
+          startPosition.x +
+          ((endPosition.x - startPosition.x) / moveFrames.length) * i,
+        y:
+          startPosition.y +
+          ((endPosition.y - startPosition.y) / moveFrames.length) * i,
+        z:
+          startPosition.z +
+          ((endPosition.z - startPosition.z) / moveFrames.length) * i,
+      };
+
+      reply['newUserStates'][0].playerState.player.angle.yaw = angle;
+
+      reply['newUserStates'][0].playerState.camera.position =
+        moveFrame.camera_position;
+      reply['newUserStates'][0].playerState.camera.angle =
+        moveFrame.camera_angle;
+      reply['newUserStates'][0].playerState.cameraCenter =
+        reply['newUserStates'][0].playerState.player.position;
+
+      reply['actionResponses'][0].traceId = traceId;
+
+      reply.mediaSrc =
+        '/' +
+        '0000000001' +
+        '/' +
+        breakPointId +
+        '/' +
+        moveFrame.file_name.substring(0, moveFrame.file_name.indexOf('.')) +
+        '/' +
+        moveFrame.file_name +
+        '?m=' +
+        new Date().getTime();
+
+      replys.push(reply);
+    }
+    return replys;
+  }
+
+  //需要通知user,人物和相机走到哪一个呼吸点位了
+  updateUser(userId, breakPointId, lastReply) {
+    const user = this.users[userId];
+    user.breakPointId = breakPointId;
+
+    user.player.position =
+      lastReply['newUserStates'][0].playerState.player.position;
+    user.player.angle = lastReply['newUserStates'][0].playerState.player.angle;
+
+    user.camera.position =
+      lastReply['newUserStates'][0].playerState.camera.position;
+    user.camera.angle = lastReply['newUserStates'][0].playerState.camera.angle;
+  }
+
+  async getBreakPoints(actionRequest) {
+    const userId = actionRequest['user_id'];
+    const traceId = actionRequest['trace_id'];
+    const actionType = actionRequest['action_type'];
+
+    const user = this.users[userId];
+    const appId = user.appId;
+    const breakPointId = user.breakPointId;
+
+    const reply = {
+      actionType: actionType,
+      pointType: 100,
+      extra: '',
+      traceId: traceId,
+      packetId: '',
+      nps: [],
+      peopleNum: 0,
+      zoneId: '',
+      echoMsg: '',
+      reserveDetail: null,
+      userWithAvatarList: [],
+      newUserStates: [],
+      code: 0,
+      msg: '',
+    };
+
+    //const breakPoints = await this.cacheService.get('breakpoints:app_id:'+appId+':break_point_id:'+breakPointId);
+    //获取redis表全部元素,'breakpoints:app_id:'+appId+':break_point_id:'开头的
+    const breakPoints = [];
+    for (let i = 0; i < breakPoints.length; ++i) {
+      const position = breakPoints[i].position;
+      reply['nps'].push(position);
+    }
+    return reply;
+  }
+
+  getAngle(point, point1, point2) {
+    const x1 = point1.x - point.x;
+    const y1 = point1.y - point.y;
+
+    const x2 = point2.x - point.x;
+    const y2 = point2.y - point.y;
+
+    const dot = x1 * x2 + y1 * y2;
+    const det = x1 * y2 - y1 * x2;
+    const angle = (Math.atan2(det, dot) / Math.PI) * 180;
+    return (angle + 360) % 360;
+  }
+}

+ 1 - 1
src/rotate/rotate.service.ts

@@ -266,7 +266,7 @@ export class RotateService {
       const redisData = await this.cacheService.get(key);
       if (redisData && redisData.length > 0) {
         const value = redisData ? JSON.parse(redisData) : null;
-        console.log('rotate-service', value);
+        // console.log('rotate-service', value);
         user.camera['position'] = value ? value.cameraPosition : '';
         user.camera['angle'] = value ? value.cameraAngle : '';
 

+ 2 - 0
src/scene/scene.module.ts

@@ -7,6 +7,7 @@ import { StreamService } from './stream/stream.service';
 import { BullModule } from '@nestjs/bull';
 import { RotateConsumer } from './rotate-consumer';
 import { RotateService } from '../rotate/rotate.service';
+import { MoveService } from '../move/move.service';
 
 @Module({
   imports: [
@@ -22,6 +23,7 @@ import { RotateService } from '../rotate/rotate.service';
     StreamService,
     RotateService,
     RotateConsumer,
+    MoveService,
   ],
   exports: [SceneService, CacheService],
 })

+ 129 - 110
src/scene/scene.service.ts

@@ -4,7 +4,7 @@ import { grpcClientOptions } from './grpc-scene.options';
 import { Logger } from '@nestjs/common';
 import { DataChannel } from 'node-datachannel';
 import * as path from 'path';
-import { BehaviorSubject } from 'rxjs';
+import { BehaviorSubject, filter, ignoreElements, take } from 'rxjs';
 // import * as streamBuffers from 'stream-buffers';
 import { ActionType } from './actionType';
 import { CacheService } from 'src/cache/cache.service';
@@ -13,6 +13,7 @@ import { InjectQueue } from '@nestjs/bull';
 import { Queue } from 'bull';
 import { RotateService } from 'src/rotate/rotate.service';
 import { DelayQueue, RxQueue, ThrottleQueue, DebounceQueue } from 'rx-queue';
+import { MoveService } from 'src/move/move.service';
 
 @Injectable()
 export class SceneService implements OnModuleInit, OnModuleDestroy {
@@ -20,8 +21,9 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
     private cacheService: CacheService,
     private streamService: StreamService,
     private rotateService: RotateService,
+    private moveService: MoveService,
     @InjectQueue('rotate') private rotateQueue: Queue,
-  ) { }
+  ) {}
   @Client(grpcClientOptions) private readonly client: ClientGrpc;
   private sceneGrpcService: SceneGrpcService;
 
@@ -34,16 +36,22 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
   private user_id: string;
   private roomId: string;
   private onSteaming = false;
-  private testFrame = -1;
   private rotateframeCnt = -1;
+  private moveframeCnt = -1;
   private mockserverTime = Date.now() - 1653000000478;
   private lastRenderMedia = '';
   private frameCnt = new BehaviorSubject<number>(-1);
   private frameCntSubscription: any;
   private roQueueSubscription: any;
+  private moveQueueSubscription: any;
+
   private streamServiceSub: any;
-  private roQueue: RxQueue = new ThrottleQueue(50);
+  private roQueue: RxQueue = new ThrottleQueue(120);
+  private moveQueue: RxQueue = new DelayQueue(1000);
   private rotateTimeStamp: number;
+  private lastMoveCnt = -1;
+  private currentMoveMaker = '';
+  private onMoving = false;
 
   onModuleInit(): void {
     this.sceneGrpcService =
@@ -72,12 +80,12 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
   }
 
   resumeStream(value: number) {
-    this.frameCnt.next(value);
     clearTimeout(this._frameTimeout);
     clearInterval(this._frameInteval);
+    this.frameCnt.next(value);
     this._frameTimeout = setTimeout(() => {
       this._frameInteval = setInterval(async () => {
-        const next = this.frameCnt.value + 1;
+        const next = this.frameCnt.getValue() + 1;
         this.frameCnt.next(next);
       }, 1000);
     }, 1000);
@@ -86,16 +94,23 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
   stopStream(): void {
     if (this.frameCntSubscription) {
       this.frameCntSubscription.unsubscribe();
+      this.frameCntSubscription = null;
     }
     if (this.roQueueSubscription) {
       this.roQueueSubscription.unsubscribe();
+      this.roQueueSubscription = null;
+    }
+    if (this.moveQueueSubscription) {
+      this.moveQueueSubscription.unsubscribe();
+      this.moveQueueSubscription = null;
     }
     this.frameCnt.next(-1);
     clearInterval(this._frameInteval);
     this.rotateframeCnt = -1;
+    this.moveframeCnt = -1;
   }
 
-  setConfig(user_id: string, roomId: string) {
+  setConfig(user_id: string, roomId: string): void {
     this.user_id = user_id;
     this.roomId = roomId;
   }
@@ -120,6 +135,7 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
       //   console.log('initReply', reply);
       // });
       this.rotateService.init(request.app_id, request.user_id);
+      this.moveService.init(request.app_id, request.user_id);
     } catch (error) {
       console.log('error', error);
     }
@@ -141,19 +157,24 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
       // this.rotateQueue.add(request, {
       //   jobId: request.trace_id,
       // });
+      if (!this.roQueueSubscription) {
+        this.handleRotateStream();
+      }
       if (!this.onSteaming) {
+        this.onMoving = false;
         const redisMeta = await this.rotateService.rotate(request);
         if (redisMeta && 'mediaSrc' in redisMeta) {
           const mediaSrc: string = redisMeta.mediaSrc || '';
           if (mediaSrc.length > 0) {
             let src = mediaSrc.split('?')[0];
             // 临时本地替换路经
-            src = src.replace('/0000000001/100/', '');
+            src = src.replace('/0000000001/', '');
             // 判断不是同一条源时才推出
             if (this.lastRenderMedia !== src) {
               console.log('[media]', src);
               // console.log('不同源');
               // this.frameCnt += 1;
+
               this.holdSteam();
               this.lastRenderMedia = src;
               const clipPath = path.join(__dirname, `../ws/video/${src}`);
@@ -255,99 +276,39 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
     // this.streamService.pushFrameToSteam(stream);
   }
 
-  walking(request) {
+  async walking(request) {
     console.log('walking', request);
-    console.log('walking-onSteaming', this.onSteaming);
-
-    const walk1 = {
-      traceIds: [request.trace_id],
-      vehicle: null,
-      newUserStates: [
-        {
-          userId: request.user_id,
-          playerState: {
-            roomTypeId: '',
-            person: 0,
-            avatarId: '',
-            skinId: '',
-            roomId: '',
-            isHost: false,
-            isFollowHost: false,
-            skinDataVersion: '',
-            avatarComponents: '',
-            nickName: '',
-            movingMode: 0,
-            attitude: '',
-            areaName: '',
-            pathName: '',
-            pathId: '',
-            avatarSize: 1,
-            extra: '',
-            prioritySync: false,
-            avatarURL: '',
-            micStatus: 0,
-            player: {
-              position: { x: -755, y: -1450, z: -34 },
-              angle: { pitch: 0, yaw: 348, roll: 4.5912e-41 },
-            },
-            camera: {
-              position: { x: -1075, y: -1450, z: 86 },
-              angle: { pitch: 0, yaw: 0, roll: 0 },
-            },
-            cameraCenter: { x: -755, y: -1450, z: -34 },
-          },
-          renderInfo: {
-            renderType: 0,
-            videoFrame: null,
-            cameraStateType: 3,
-            isMoving: 1,
-            needIfr: 0,
-            isVideo: 0,
-            stillFrame: 0,
-            isRotating: 0,
-            isFollowing: 0,
-            clientPanoTitlesBitmap: [],
-            clientPanoTreceId: '',
-            prefetchVideoId: '',
-            noMedia: false,
-          },
-          event: null,
-          relation: 1,
-        },
-      ],
-      actionResponses: [
-        {
-          actionType: 1,
-          pointType: 0,
-          extra: '',
-          traceId: request.trace_id,
-          packetId: '',
-          nps: [],
-          peopleNum: 0,
-          zoneId: '',
-          echoMsg: '',
-          reserveDetail: null,
-          userWithAvatarList: [],
-          newUserStates: [],
-          code: 0,
-          msg: '',
-        },
-      ],
-      getStateType: 0,
-      code: 0,
-      msg: 'OK',
-    };
-    const nextframe = this.frameCnt.value + 1;
-
-    const stream: StreamFrameType = {
-      frame: nextframe,
-      clipPath: path.join(__dirname, `../ws/video/2.h264`),
-      metaData: JSON.stringify(walk1),
-      serverTime: this.mockserverTime,
-      DIR: 3,
-    };
-    console.log('walking', this.frameCnt, stream.clipPath);
-    this.streamService.pushFrameToSteam(stream);
+
+    const walkingRes = await this.moveService.move(request);
+    if (walkingRes) {
+      this.onMoving = true;
+      if (!this.moveQueueSubscription) {
+        this.handleMoveSteam();
+      }
+      const res = Object.keys(walkingRes).map((item) => {
+        console.log('item', item);
+        return Array.from(walkingRes[item]).map((i) => {
+          i['marker'] = item;
+          return i;
+        });
+      });
+      const seqs = Array.from(res).flat();
+      this.lastMoveCnt = this.frameCnt.value + seqs.length;
+      console.log('lastMoveCnt', this.lastMoveCnt);
+      seqs.forEach((frame: StreamReplyType) => {
+        const mediaSrc = frame.mediaSrc;
+        delete frame.mediaSrc;
+        const stream: StreamFrameType = {
+          frame: -1,
+          clipPath: mediaSrc,
+          metaData: JSON.stringify(frame),
+          serverTime: this.mockserverTime,
+          DIR: 1,
+        };
+        this.moveQueue.next(stream);
+      });
+      this.holdSteam();
+    }
   }
 
   handleBreath(request) {
@@ -499,6 +460,7 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
   pushFirstRender(clipPath: string, metaData: string): Promise<boolean> {
     return new Promise<boolean>(async (resolve, reject) => {
       try {
+        this.onSteaming = true;
         const streamData: StreamFrameType = {
           frame: 1,
           clipPath: clipPath,
@@ -519,12 +481,14 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
         console.log('frame', frame);
         if (frame === 1) {
           const redisData = await this.rotateService.echo(this.user_id);
+          this.onSteaming = true;
+          this.holdSteam();
           if (redisData && 'mediaSrc' in redisData) {
             const mediaSrc: string = redisData.mediaSrc || '';
             if (mediaSrc.length > 0) {
               let src = mediaSrc.split('?')[0];
               // 临时本地替换路经
-              src = src.replace('/0000000001/100/', '');
+              src = src.replace('/0000000001/', '');
               const clipPath = path.join(__dirname, `../ws/video/${src}`);
               delete redisData.mediaSrc;
 
@@ -532,8 +496,6 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
                 `user:${this.user_id}:first render stream` +
                   JSON.stringify({ path: clipPath, meta: redisData }),
               );
-
-              this.holdSteam();
               const status = await this.pushFirstRender(
                 clipPath,
                 JSON.stringify(redisData),
@@ -546,35 +508,35 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
             }
           }
         }
+        console.log(`空白流::${frame}-onSteaming`, this.onSteaming);
         if (frame > 1 && !this.onSteaming) {
           const redisDataAuto = await this.rotateService.echo(this.user_id);
           if (redisDataAuto) {
+            'mediaSrc' in redisDataAuto && delete redisDataAuto.mediaSrc;
             const streamMeta: StreamMetaType = {
               frame: frame,
               metaData: JSON.stringify(redisDataAuto),
             };
             this.streamService.pushMetaDataToSteam(streamMeta);
-          } else {
           }
         }
       } catch (error) {
         this.logger.error('handleStream', error);
       }
     });
-
+  }
+  handleRotateStream() {
     this.roQueueSubscription = this.roQueue.subscribe(
       async (stream: StreamFrameType) => {
         this.rotateTimeStamp = Date.now();
-
         if (this.rotateframeCnt === -1) {
           this.rotateframeCnt = this.frameCnt.value;
         }
         this.rotateframeCnt += 1;
         stream.frame = this.rotateframeCnt;
-        console.log(
-          'roQueueSubscription \n',
-          this.rotateframeCnt,
-          stream.metaData,
+        this.logger.log(
+          `roQueueSubscription:frame:${this.rotateframeCnt}   ` +
+            JSON.stringify(stream.metaData),
         );
         await this.streamService.pushFrameToSteam(stream);
         setTimeout(() => {
@@ -583,9 +545,66 @@ export class SceneService implements OnModuleInit, OnModuleDestroy {
             const next = this.rotateframeCnt + 1;
             this.resumeStream(next);
             this.rotateframeCnt = -1;
+            this.onMoving = false;
           }
         }, 300);
       },
     );
   }
+
+  cleanMoveSteam() {
+    if (this.moveQueueSubscription) {
+      this.moveQueueSubscription.unsubscribe();
+      this.moveframeCnt = -1;
+      this.lastMoveCnt = -1;
+      this.moveQueueSubscription = null;
+    }
+  }
+  handleMoveSteam() {
+    this.moveQueueSubscription = this.moveQueue.subscribe(
+      async (stream: StreamFrameType) => {
+        const metaData: StreamReplyType = JSON.parse(stream.metaData);
+        this.holdSteam();
+        console.log('handleMoveSteam-onSteaming', this.onSteaming);
+        if (this.onMoving) {
+          this.currentMoveMaker = metaData.marker;
+        } else {
+          if (
+            this.currentMoveMaker &&
+            this.currentMoveMaker !== metaData.marker
+          ) {
+            console.log('kill Queue');
+
+            return;
+          }
+        }
+        // console.log('moveQueueSubscription', stream, metaData.marker);
+        if (this.moveframeCnt === -1) {
+          this.moveframeCnt = this.frameCnt.value;
+        }
+        this.moveframeCnt += 1;
+        console.log('this.moveframeCnt', this.moveframeCnt);
+        let src = stream.clipPath.split('?')[0];
+        // // 临时本地替换路经
+        src = src.replace('/0000000001/', '');
+        const clipPath = path.join(__dirname, `../ws/video/${src}`);
+
+        const streamData: StreamFrameType = {
+          frame: this.moveframeCnt,
+          clipPath: clipPath,
+          metaData: stream.metaData,
+          serverTime: this.mockserverTime,
+          DIR: 3,
+        };
+        await this.streamService.pushFrameToSteam(streamData);
+
+        if (this.lastMoveCnt == this.moveframeCnt) {
+          const next = this.moveframeCnt + 1;
+          console.log('last', next);
+          this.resumeStream(next);
+          this.cleanMoveSteam();
+        }
+      },
+    );
+  }
 }

+ 72 - 0
src/scene/stream/stream.d.ts

@@ -4,8 +4,80 @@ interface StreamFrameType {
   metaData: string;
   serverTime?: number;
   DIR?: number;
+  mediaSrc?: string; // 临时
 }
 interface StreamMetaType {
   frame: number;
   metaData: string;
 }
+
+// interface   newUserStates: [
+//   {
+//     userId: 'dcff36ae4fc1d',
+//     playerState: {
+//       roomTypeId: '',
+//       person: 0,
+//       avatarId: '',
+//       skinId: '',
+//       roomId: '',
+//       isHost: false,
+//       isFollowHost: false,
+//       skinDataVersion: '',
+//       avatarComponents: '',
+//       nickName: '',
+//       movingMode: 0,
+//       attitude: '',
+//       areaName: '',
+//       pathName: '',
+//       pathId: '',
+//       avatarSize: 1,
+//       extra: '',
+//       prioritySync: false,
+//       player: {
+//         position: { x: -700, y: 0, z: 0 },
+//         angle: {
+//           pitch: 0,
+//           yaw: 0,
+//           roll: 0,
+//         },
+//       },
+//       camera: {
+//         position: { x: -1145, y: 0, z: 160 },
+//         angle: {
+//           pitch: 0,
+//           yaw: 0,
+//           roll: 0,
+//         },
+//       },
+//       cameraCenter: { x: -700, y: 0, z: 0 },
+//     },
+//     renderInfo: {
+//       renderType: 0,
+//       videoFrame: null,
+//       cameraStateType: 3,
+//       isMoving: 1,
+//       needIfr: 0,
+//       isVideo: 0,
+//       stillFrame: 0,
+//       isRotating: 0,
+//       isFollowing: 0,
+//       clientPanoTitlesBitmap: [],
+//       clientPanoTreceId: '',
+//       prefetchVideoId: '',
+//       noMedia: false,
+//     },
+//     event: null,
+//     relation: 1,
+//   },
+// ],
+interface StreamReplyType {
+  traceIds: string[];
+  vehicle: string;
+  mediaSrc?: string;
+  newUserStates: any[];
+  actionResponses: any[];
+  getStateType: number;
+  code: number;
+  msg: string;
+  marker?: string;
+}

+ 1 - 1
src/scene/stream/stream.service.ts

@@ -165,7 +165,7 @@ export class StreamService {
         steam.on('end', () => {
           steamByteLength = 0;
           console.log('stream end');
-          if (this.onSteaming) {
+          if (this.onSteaming.value) {
             this.onSteaming.next(false);
           }
         });

BIN
ws/video/earth/0


BIN
ws/video/earth/1


BIN
ws/video/earth/10


BIN
ws/video/earth/100


BIN
ws/video/earth/101


BIN
ws/video/earth/102


BIN
ws/video/earth/103


BIN
ws/video/earth/104


BIN
ws/video/earth/105


BIN
ws/video/earth/106


BIN
ws/video/earth/107


BIN
ws/video/earth/108


BIN
ws/video/earth/109


BIN
ws/video/earth/11


BIN
ws/video/earth/110


BIN
ws/video/earth/111


BIN
ws/video/earth/112


BIN
ws/video/earth/113


BIN
ws/video/earth/114


BIN
ws/video/earth/115


BIN
ws/video/earth/116


BIN
ws/video/earth/117


BIN
ws/video/earth/118


BIN
ws/video/earth/119


BIN
ws/video/earth/12


BIN
ws/video/earth/120


BIN
ws/video/earth/121


BIN
ws/video/earth/122


BIN
ws/video/earth/123


BIN
ws/video/earth/124


BIN
ws/video/earth/125


BIN
ws/video/earth/126


BIN
ws/video/earth/127


BIN
ws/video/earth/128


BIN
ws/video/earth/129


BIN
ws/video/earth/13


BIN
ws/video/earth/130


BIN
ws/video/earth/131


BIN
ws/video/earth/132


BIN
ws/video/earth/133


BIN
ws/video/earth/134


BIN
ws/video/earth/135


BIN
ws/video/earth/136


BIN
ws/video/earth/137


BIN
ws/video/earth/138


BIN
ws/video/earth/139


BIN
ws/video/earth/14


BIN
ws/video/earth/140


BIN
ws/video/earth/141


BIN
ws/video/earth/142


BIN
ws/video/earth/143


BIN
ws/video/earth/144


BIN
ws/video/earth/145


BIN
ws/video/earth/146


BIN
ws/video/earth/147


BIN
ws/video/earth/148


BIN
ws/video/earth/149


BIN
ws/video/earth/15


BIN
ws/video/earth/150


BIN
ws/video/earth/151


BIN
ws/video/earth/152


BIN
ws/video/earth/153


BIN
ws/video/earth/154


BIN
ws/video/earth/155


BIN
ws/video/earth/156


BIN
ws/video/earth/157


BIN
ws/video/earth/158


BIN
ws/video/earth/159


BIN
ws/video/earth/16


BIN
ws/video/earth/160


BIN
ws/video/earth/161


BIN
ws/video/earth/162


BIN
ws/video/earth/163


BIN
ws/video/earth/164


BIN
ws/video/earth/165


BIN
ws/video/earth/166


BIN
ws/video/earth/167


BIN
ws/video/earth/168


BIN
ws/video/earth/169


BIN
ws/video/earth/17


BIN
ws/video/earth/170


BIN
ws/video/earth/171


BIN
ws/video/earth/172


BIN
ws/video/earth/173


BIN
ws/video/earth/174


BIN
ws/video/earth/175


BIN
ws/video/earth/176


BIN
ws/video/earth/177


BIN
ws/video/earth/178


BIN
ws/video/earth/179


BIN
ws/video/earth/18


+ 0 - 0
ws/video/earth/180


Some files were not shown because too many files changed in this diff