ios - 在给定时间捕获 AVPlayer 流 .m3u8 的 UIImage 帧?

标签 ios objective-c uiimage calayer avplayer

所以我有一个 AVPlayer 播放 .m3u8 视频的实时流,从我发现的搜索结果来看,你不能使用 AVAssetImageGenerator 来制作屏幕截图,而应该使用 AVPlayerItemVideoOutput 和

- (CVPixelBufferRef)copyPixelBufferForItemTime:(CMTime)itemTime itemTimeForDisplay:(CMTime *)outItemTimeForDisplay

但是当我尝试从我的 AVPlayer 获取输出时。

NSArray *outputs = self.mainPlayer.currentItem.outputs;

我得到一个空数组。

视频播放得很好。最终我想要的是这样的方法。

-(UIImage *)frameFor:(CMTime)time;

在某些时候, View 上的 CALayer 需要获取此图像数据,因此它们必须是一种在某些时候获取该数据的方法。我尝试只捕获我的 AVPLayerLayer 附加到的 CALayer,但除了空白 View 颜色(亮粉色只是为了确保它返回一些东西)之外我没有得到任何东西。他们必须以某种方式获取这些数据。

最佳答案

当你这样做时你会得到一个空数组

NSArray *outputs = self.mainPlayer.currentItem.outputs;

因为需要先添加AVPlayerItemVideoOutput对象

NSDictionary *settings = @{(id)kCVPixelBufferPixelFormatTypeKey : [NSNumber numberWithInt:kCVPixelFormatType_32BGRA]};
self.videoOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:settings];
[playerItem addOutput:self.videoOutput];

然后当 AVPlayerItem 状态为 AVPlayerStatusReadyToPlay 时,您可以使用 copyPixelBufferForItemTime:itemTimeForDisplay 捕获当前帧。为此,您需要创建 AVPlayer 对象并将观察者添加到 AVPlayerItem 状态属性

self.player = [AVPlayer playerWithPlayerItem:playerItem];
[self.player.currentItem addObserver:self forKeyPath:@"status" options:0 context:NULL];

然后在你的回调函数中

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (self.player.currentItem.status == AVPlayerStatusReadyToPlay)
    {
        CMTime currentTime = self.player.currentItem.currentTime;
        CVPixelBufferRef buffer = [self.videoOutput copyPixelBufferForItemTime:currentTime itemTimeForDisplay:nil];

        CIImage *ciImage = [CIImage imageWithCVPixelBuffer:buffer];
        UIImage *image = [UIImage imageWithCIImage:ciImage];

        // use `image`
    }
}

如果您只需要捕获缩略图而不必先播放视频,则可以使用我创建的遵循此逻辑的简单实用程序。 ( https://github.com/acotilla91/ACThumbnailGenerator )

使用方法:

double bitRate = 1000000; // force video bit rate (can be use to cap video quality and improve performance). Pass 0 to use default bit rate.
self.thumbnailGenerator = [[ACThumbnailGenerator alloc] initWithPreferredBitRate:bitRate];

NSURL *videoURL = [NSURL URLWithString:@"http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/sl.m3u8"];
int position = 10; // video position (in seconds) from where thumbnail should be extracted. Always pass 0 for live streams.

[self.thumbnailGenerator loadImageFrom:videoURL position:position withCompletionBlock:^(UIImage *image) {

    // use `image`            

}];

希望对您有所帮助。

Swift 版本:
ACThumbnailGenerator-Swift

用法:

var generator: ACThumbnailGenerator!

func captureSomeImage() {
    let streamUrl = URL(string: "https://p-events-delivery.akamaized.net/18oijbasfvuhbfsdvoijhbsdfvljkb6/m3u8/hls_vod_mvp.m3u8")!
    generator = ACThumbnailGenerator(streamUrl: streamUrl)
    generator.delegate = self
    generator.captureImage(at: 300)
}

func generator(_ generator: ACThumbnailGenerator, didCapture image: UIImage, at position: Double) {
    // Use `image`
}

关于ios - 在给定时间捕获 AVPlayer 流 .m3u8 的 UIImage 帧?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33269314/

相关文章:

ios - 如何从 NSDate 获取小时和分钟?

ios - 如何在 objective-c 中为每个用户在其整个生命周期中只运行一次代码

ios - 在不同的显示器上 react native 相同大小的圆圈

ios - 超出自定义单元格边界的披露指示符

ios - UIPopoverController 内的导航

ios - 使用 Swift (AutoLayout) 修复 UIImage 的宽度和高度

ios - 如何将 iOS 应用程序窗口的背景图像居中

iphone - ipad ScrollView 导致 malloc 为图像大小的 40 倍

iOS:如何阻止后台线程在主线程中更新 UI?

ios - UISearchBar - UISearchBar 的不同表格 View 背景