【发布时间】:2020-09-18 22:12:42
【问题描述】:
我正在尝试逐帧处理视频文件。我不需要将帧保存到图像。
有一些关于这个主题的问答 (e.g.)。但是MediaComposition.GetThumbnailAsync 很慢。也有FFmpeg UWP 项目有图像采集卡,但也不是很快...
所以我利用了自定义IBasicVideoEffect,它实现了处理每一帧的方法(ProcessFrame)。这正是我需要的。这里的问题是,我不知道如何调用 ProcessFrame 方法。唯一的想法是在 MediaPlayerElement 中播放视频或将具有效果的合成保存到文件中。但我需要在后台快速处理视频文件,无需重播,无需渲染另一个文件。
这里是渲染文件的解决方案(目前更快的图像采集卡...)
//Page.Loaded
private async void LoadedAsync(object sender, RoutedEventArgs e)
{
//set file to process
StorageFile videoFile = await Package.Current.InstalledLocation.GetFileAsync("big_buck_bunny.mp4");
//create clip from file
MediaClip clip = await MediaClip.CreateFromFileAsync(videoFile);
//apply "effect" on clip
var vefdef = new VideoEffectDefinition(typeof(VideoEffectReachFrames).FullName);
clip.VideoEffectDefinitions.Add(vefdef);
//create composition
compositor = new MediaComposition();
compositor.Clips.Add(clip);
}
MediaComposition compositor;
private async void Button_ClickAsync(object sender, RoutedEventArgs e)
{
//create temp file
var tempFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("tempFile.mp4", CreationCollisionOption.ReplaceExisting);
//HERE - I need to render file.
await compositor.RenderToFileAsync(tempFile);//render to file to evoke VideoEffect..
}
以及 Effect 类中的 ProcessFrame 方法:
public void ProcessFrame(ProcessVideoFrameContext context)
{
//Getting pixel data, I am fine here
var inputFrameBitmap = context.InputFrame.SoftwareBitmap;
var frameSize = inputFrameBitmap.PixelWidth * inputFrameBitmap.PixelHeight * 4;
var frameBuffer = new Buffer((uint)frameSize);
context.InputFrame.SoftwareBitmap.CopyToBuffer(frameBuffer);
var framePixels = frameBuffer.ToArray();
Debug.WriteLine($"Touching 25th red pixel {framePixels[100]}");
}
如何在MediaComposition 的帮助下到达帧而不渲染不必要的文件?
【问题讨论】:
-
您好,这种渲染是必须的。它需要从字节流转换为图像,并且图像必须序列化为视频。虽然没有在后台显示,但是应用还是需要渲染
-
我基本上只是在寻找“从字节流转换为图像”...没有办法只使用该过程的那一部分吗?
-
我不太明白你的意图。事实上,字节流本身就是一个图像。如果渲染一个字节流(例如将其转换为
BitmapImage作为Image控件的源),它将显示为图像。如果将字节流保存为文件,则为图像文件(根据文件类型,可能需要编码) -
我的意图是获取那个字节流(图像)。问题是我需要将视频渲染到文件以获取单个视频帧(在 ProcessFrame 方法中)。必须有某种方法可以做到这一点......我只是没有找到它,我猜......
-
您好,目前这个过程可能是必要的,您需要先将字节流编码成图片再进行处理。处理完成后可以删除临时图片