将视频帧转换为流式视频
Posted
技术标签:
【中文标题】将视频帧转换为流式视频【英文标题】:turn video frames to streaming video 【发布时间】:2018-08-20 16:41:38 【问题描述】:服务器正在发送视频帧。我想使用它们来进行流式传输。我想知道如何组装帧来创建流媒体视频。到目前为止,我可以将帧显示为图片。下面是我的角度代码
组件角度
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" />
我正在尝试使用相机的帧速率更改图片。但是我的图片没有更新,由于 http 请求的数量很大,它冻结了我的浏览器。
我想要实现的是缓冲帧以便使用 video
标签而不是 img
标签,就像我使用 video
标签连接到服务器发送的实时流一样src
设置为服务器的url
。
Github 链接:https://github.com/kedevked/frameProcessing
【问题讨论】:
为什么不只渲染视频呢?而不是返回帧图像? 因为服务器发送的是图片,而不是视频。<video src ="url" ></video>
不会显示任何内容
我不认为它会那样工作。它会很慢并且会消耗大量带宽。也许尝试降低帧率。让另一台服务器读取这些帧并将它们转换回视频是一种选择吗?
我不能考虑使用另一台服务器进行处理
@edkeveked,很有趣。能否提供api返回图片或者更好的示例项目给github?
【参考方案1】:
与其以一定的时间间隔触发http请求,不如使用websocket。
通过逐帧显示图像,它给人一种现场视频的印象。唯一的问题是网络中可能存在延迟,这使得帧速率不是恒定的。但是,它适用于无法考虑缓冲视频服务器端的用例,例如当我们需要沿每一帧发送数据时。
使用 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%,因此在所有设置中使用它可能成本很高。如果图像需要与其他数据一起提供,则可以将整个数据作为二进制发送。这将需要在服务器端对数据进行编码并在客户端对其进行解码。 由于这可能需要一些计算,因此可以考虑使用 web-worker 不仅可以解码数据,还可以显示图像。
如果图片以二进制形式发送,使用canvas进行渲染会更快
canvas.getContex('2d').putImageData(imageBinaryData, 0, 0)
【讨论】:
base64 不会增加 133%,而不是 1.33%? 感谢您发现错误,我编辑了答案【参考方案2】:我在这里看到两个问题,这可能会改进此解决方案。
首先,你怎么知道请求会花费不到 250 毫秒?如果没有,你知道 switchMap 会取消它吗?如果您不想丢失当前的请求,也许 exhaustMap 或 concatMap 更适合。
第二点是间隔(X)和HTTP请求在角度区域内,所以它们会触发变化检测......这可能会给您带来几个性能问题。因此,您应该在区域外运行间隔和请求并手动检测更改。
说我会设计一个这样的解决方案:
private subscription: Subscription;
cosntructor(public ngZone: NgZone, public cd: ChangeDetectorRef)
getVideo();
getVideo()
this.subscription = this.ngZone.runOutsideAngular(() =>
interval(250).pipe(exhaustMap(() => 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()
我认为使用此代码不会有很多性能问题...尽管这种类型的长轮询从来都不是很好,但我认为它不会冻结您的应用程序。试试看,然后告诉我。
希望这会有所帮助。
【讨论】:
我真正想做的是缓冲帧,以便拥有可以在video
标签中使用的视频。
嗨@edkeveked,鉴于您的情况,首选的解决方案是使用图像标签,您不能缓冲 getPictures() 等并将其转换为视频格式,尽管它没有意义。如果您想这样做,只需更改您的服务并设置一些 WebRTC 连接或提供视频内容的 sov。是我的推荐。虽然,试试我的解决方案,它可能会很好。
代码抛出此错误:interval().concatMap() is not a function
。您能否提供一个使用 WebRTC 时的工作示例,我们可以从服务器而不是设备摄像头获取帧,然后将其转换为视频?
@edkeveked 抱歉,我忘记了管道操作员。我不能给你举个例子,太多了。这意味着服务器端、客户端等方面的变化...查看 kurento kurento.org,他们有很好的文档和已经完成的代码,以便在服务器和客户端上使用 webRTC。以上是关于将视频帧转换为流式视频的主要内容,如果未能解决你的问题,请参考以下文章