fra*_*yan 9 video objective-c avfoundation ios avplayer
我花了一整天时间,经历了很多SO答案,Apple参考文献,文档等,但都没有成功.
我想要一个简单的事情:我正在使用AVPlayer播放视频,我想暂停它并获取当前帧UIImage.而已.
我的视频是一个位于互联网上的m3u8文件,它在AVPlayerLayer没有任何问题的情况下正常播放.
我试过了什么:
AVAssetImageGenerator.它不起作用,该方法copyCGImageAtTime:actualTime: error:返回null image ref.根据答案,此处 AVAssetImageGenerator不适用于流媒体视频.renderInContext:的AVPlayerLayer,但后来我意识到,这不是渲染这种"特殊"层.然后我发现了iOS 7中引入的一种新方法 - drawViewHierarchyInRect:afterScreenUpdates:它应该能够渲染特殊的图层,但没有运气,仍然可以获得带有空白黑色区域的UI快照,其中显示视频.AVPlayerItemVideoOutput.我为我添加了一个视频输出AVPlayerItem,但每当我调用hasNewPixelBufferForItemTime:它时返回NO.我想问题是再次流式传输视频,我并不孤单.AVAssetReader.我正在考虑尝试,但决定在这里找到相关问题后不要浪费时间.所以,有没有办法得到我现在在屏幕上看到的东西的快照?我简直不敢相信.
AVPlayerItemVideoOutput从m3u8对我来说效果很好。也许是因为我不咨询hasNewPixelBufferForItemTime而只是打电话copyPixelBufferForItemTime吗?这段代码产生了a CVPixelBuffer而不是a UIImage,但是有描述如何做到的答案。
这个答案大多来自这里
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
@interface ViewController ()
@property (nonatomic) AVPlayer *player;
@property (nonatomic) AVPlayerItem *playerItem;
@property (nonatomic) AVPlayerItemVideoOutput *playerOutput;
@end
@implementation ViewController
- (void)setupPlayerWithLoadedAsset:(AVAsset *)asset {
NSDictionary* settings = @{ (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) };
self.playerOutput = [[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:settings];
self.playerItem = [AVPlayerItem playerItemWithAsset:asset];
[self.playerItem addOutput:self.playerOutput];
self.player = [AVPlayer playerWithPlayerItem:self.playerItem];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
playerLayer.frame = self.view.frame;
[self.view.layer addSublayer:playerLayer];
[self.player play];
}
- (IBAction)grabFrame {
CVPixelBufferRef buffer = [self.playerOutput copyPixelBufferForItemTime:[self.playerItem currentTime] itemTimeForDisplay:nil];
NSLog(@"The image: %@", buffer);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *someUrl = [NSURL URLWithString:@"http://qthttp.apple.com.edgesuite.net/1010qwoeiuryfg/sl.m3u8"];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:someUrl options:nil];
[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler:^{
NSError* error = nil;
AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:&error];
if (status == AVKeyValueStatusLoaded)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self setupPlayerWithLoadedAsset:asset];
});
}
else
{
NSLog(@"%@ Failed to load the tracks.", self);
}
}];
}
@end
Run Code Online (Sandbox Code Playgroud)
AVAssetImageGenerator是拍摄视频快照的最佳方式,此方法异步返回UIImage:
import AVFoundation
// ...
var player:AVPlayer? = // ...
func screenshot(handler:@escaping ((UIImage)->Void)) {
guard let player = player ,
let asset = player.currentItem?.asset else {
return
}
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
let times = [NSValue(time:player.currentTime())]
imageGenerator.generateCGImagesAsynchronously(forTimes: times) { _, image, _, _, _ in
if image != nil {
handler(UIImage(cgImage: image!))
}
}
}
Run Code Online (Sandbox Code Playgroud)
(这是Swift 4.2)
| 归档时间: |
|
| 查看次数: |
6941 次 |
| 最近记录: |