将视频帧转换为流式视频

时间:2018-03-12 15:33:14

标签: javascript angular html5-video

服务器正在发送视频帧。我想用它们来做流式传输。我想知道如何组装帧以创建流式视频。到目前为止,我可以将帧显示为图片。下面是我的角度代码

组件角度

 getVideo() {
    interval(250).switchMap(() => this.appService.getPictures())
      .subscribe(data => {
        const file = new Blob([data], {type:'image/png'});
        this.url = this.sanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(file));
      })
  }

模板html

<img div="test" [src]="url" width="400px" height="300px"/>

我正在尝试使用相机的帧速率更改图片。但我的图片没有更新,由于http请求数量很多,它冻结了我的浏览器。

我想要实现的是缓冲帧以便使用video标记而不是img标记,就像我使用{连接到服务器的实时流式传输一样{1}} video标记设置为服务器的src

Github链接:https://github.com/kedevked/frameProcessing

2 个答案:

答案 0 :(得分:4)

使用websocket更好,而不是在一定的时间间隔内触发http请求。

通过逐帧显示图像,可以给人以现场视频的印象。但是唯一的事情是网络中可能存在等待时间,这使得帧速率不恒定。但是,它适用于无法考虑缓冲视频服务器端的用例,例如当我们需要沿着每个帧发送数据时。

使用websocket的服务

createStream(url) {
  this.ws = webSocket<any>(url);
  return return this.ws.asObservable()
}

组件

constructor (private streamingService: StreamingService) {}
ngOnInit(): void { 
  this.getStream()
}

getStream() {
  this.streamingService.createStream().subscribe(data => {
    const file = new Blob([data], {type:'image/png'});
        this.url = this.sanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(file));
 })
}

当我们不仅要发送图像,还要发送图像数据时,此解决方案非常适合。在这种情况下,该图像需要作为base64发送。

getStream() {
      this.streamingService.createStream().subscribe(data => {
            this.url = data.base64ImageData
     })
    }

由于base64编码的有效负载为初始图像的133%,因此在所有设置中使用它可能会很昂贵。如果图像需要与其他数据一起提供,则整个数据可以二进制形式发送。这将需要在服务器端对数据进行编码,并在客户端对其进行解码。 由于这可能需要一些计算,因此可以考虑使用网络工作者不仅对数据进行解码,而且还考虑显示图像。

如果图像以二进制形式发送,则使用画布进行渲染会更快

canvas.getContex('2d').putImageData(imageBinaryData, 0, 0)

答案 1 :(得分:0)

我在这里看到两个问题,这可能会改善此解决方案。

首先,您如何知道请求的花费时间不会超过250毫秒?如果没有,你知道switchMap会取消它吗?如果您不想丢失请求, concatMap 可能会更合适。

第二点是间隔(X)和HTTP请求在角度区域内,因此它们将触发变化检测......这可能会带来一些性能问题。因此,您应该在区域外运行间隔和请求,并手动检测更改

说我会提出这样的解决方案:

private subscription: Subscription;
cosntructor(public ngZone: NgZone, public cd: ChangeDetectorRef){
   getVideo();
}

getVideo() {
    this.subscription = this.ngZone.runOutsideAngular(() => 
         interval(250).pipe(concatMap(() => this.appService.getPictures()))
           .subscribe(data => {
              const file = new Blob([data], {type:'image/png'});
              this.url = this.sanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(file));
              // Do change detection in orther to actualize [url] binding
              this.cd.detectChanges();
           })
    );
}
ngOnDestroy() {
    // remember to unsubscribe from interval subscription
    this.subscription.unsubscribe()
}

我不认为使用此代码会有很多性能问题......虽然这种类型的长轮询永远不会好,但我认为它不会冻结您的应用。试试吧,让我知道。

希望这有帮助。