服务器正在发送视频帧。我想用它们来做流式传输。我想知道如何组装帧以创建流式视频。到目前为止,我可以将帧显示为图片。下面是我的角度代码
组件角度
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
。
答案 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()
}
我不认为使用此代码会有很多性能问题......虽然这种类型的长轮询永远不会好,但我认为它不会冻结您的应用。试试吧,让我知道。
希望这有帮助。