ios - framework - iPhone Lee UIimage(cuadros) de video con AVFoundation
avfoundation framework (5)
Código Swift 2 para tomar cuadros con AVAssetImageGenerator:
func previewImageForLocalVideo(url:NSURL) -> UIImage?
{
let asset = AVAsset(URL: url)
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
var time = asset.duration
//If possible - take not the first frame (it could be completely black or white on camara''s videos)
time.value = min(time.value, 2)
do {
let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)
return UIImage(CGImage: imageRef)
}
catch let error as NSError
{
print("Image generation failed with error /(error)")
return nil
}
}
Lo siento por mi inglés) Buscando información sobre cómo leer marcos de un video con iPhone, encontré este proyecto, http://www.codza.com/extracting-frames-from-movies-on-iphone/comment-page-1#comment-1116 , pero también leí en alguna parte que puede usar AVFoundation para capturar cuadros de un video para un mejor rendimiento ...
Pero no puedo encontrar información de cómo puedo hacer eso ...
¿Alguna idea?
Gracias por leer
En Swift 4 esto me funcionó con algunas modificaciones, principalmente cambiando el parámetro "at" de imageGenerator.copyCGImage a un tipo CMTime:
func showFrame(from file:String) {
let file = file.components(separatedBy: ".")
guard let path = Bundle.main.path(forResource: file[0], ofType:file[1]) else {
debugPrint( "/(file.joined(separator: ".")) not found")
return
}
let url = URL(fileURLWithPath: path)
let image = previewImageForLocalVideo(url: url)
let imgView = UIImageView(image: image)
view.addSubview(imgView)
}
func previewImageForLocalVideo(url:URL) -> UIImage? {
let asset = AVAsset(url: url)
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
let tVal = NSValue(time: CMTimeMake(12, 1)) as! CMTime
do {
let imageRef = try imageGenerator.copyCGImage(at: tVal, actualTime: nil)
return UIImage(cgImage: imageRef)
}
catch let error as NSError
{
print("Image generation failed with error /(error)")
return nil
}
}
override func viewDidLoad() {
super.viewDidLoad()
showFrame(from:"video.mp4")
}
Está hablando de usar las llamadas para generar lo que Apple llama imágenes en miniatura de videos en momentos específicos.
Para un MPMoviePlayerController (lo que iOS usa para guardar un video de un archivo u otra fuente), hay dos comandos para hacer esto. La primera genera una única miniatura (imagen) de una película en un punto específico en el tiempo, y la segunda genera un conjunto de miniaturas para un rango de tiempo.
Este ejemplo obtiene una imagen a los 10 segundos en un clip de película, myMovie.mp4 :
MPMoviePlayerController *movie = [[MPMoviePlayerController alloc]
initWithContentURL:[NSURL URLWithString:@"myMovie.mp4"]];
UIImage *singleFrameImage = [movie thumbnailImageAtTime:10
timeOption:MPMovieTimeOptionExact];
Tenga en cuenta que esto se realiza de forma síncrona, es decir, el usuario se verá obligado a esperar mientras obtiene la captura de pantalla.
La otra opción es obtener una serie de imágenes de una película, de una variedad de veces:
MPMoviePlayerController *movie = [[MPMoviePlayerController alloc]
initWithContentURL [NSURL URLWithString:@"myMovie.mp4"]];
NSNumber time1 = 10;
NSNumber time2 = 11;
NSNumber time3 = 12;
NSArray *times = [NSArray arrayWithObjects:time1,time2,time3,nil];
[movie requestThumbnailImagesAtTimes:times timeOption:MPMovieTimeOptionExact];
Esta segunda forma activará una notificación de tipo MPMoviePlayerThumbnailImageRequestDidFinishNotification
cada vez que se genere una nueva imagen. Puedes configurar un observador para monitorear esto y procesar la imagen. ¡Te dejaré que trabajes un poco por tu cuenta!
También puedes probar AVAssetImageGenerator , específicamente AVAssetImageGenerator generateCGImagesAsynchronouslyForTimes:completionHandler .
Esta respuesta SO tiene buen código de ejemplo.
Aquí está el código para obtener imágenes FPS de video
1) Importar
#import <Photos/Photos.h>
2) en viewDidLoad
videoUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:@"VfE_html5" ofType:@"mp4"]];
[self createImage:5]; // 5 is frame per second (FPS) you can change FPS as per your requirement.
3) Funciones
-(void)createImage:(int)withFPS {
AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:videoUrl options:nil];
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.requestedTimeToleranceAfter = kCMTimeZero;
generator.requestedTimeToleranceBefore = kCMTimeZero;
for (Float64 i = 0; i < CMTimeGetSeconds(asset.duration) * withFPS ; i++){
@autoreleasepool {
CMTime time = CMTimeMake(i, withFPS);
NSError *err;
CMTime actualTime;
CGImageRef image = [generator copyCGImageAtTime:time actualTime:&actualTime error:&err];
UIImage *generatedImage = [[UIImage alloc] initWithCGImage:image];
[self savePhotoToAlbum: generatedImage]; // Saves the image on document directory and not memory
CGImageRelease(image);
}
}
}
-(void)savePhotoToAlbum:(UIImage*)imageToSave {
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:imageToSave];
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"sucess.");
}
else {
NSLog(@"fail.");
}
}];
}