在给定时间内捕获AVPlayer流式传输.m3u8的UIImage帧?

时间:2015-10-21 21:09:59

标签: ios objective-c uiimage calayer avplayer

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

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

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

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

我得到一个空数组。

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

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

在某些时候,视图上的CALayer需要获取此图像数据,因此它们必须是某种方式来获取它的方法。我尝试抓住我的AVPLayerLayer附加的CALayer,但我得到的不仅仅是空白视图颜色(亮粉色只是为了确保它返回的东西)。他们必须以某种方式获取这些数据。

1 个答案:

答案 0 :(得分:0)

当您执行

时,您将获得一个空数组
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`
}