Создание миниатюры для видео в iOS - PullRequest
19 голосов
/ 11 мая 2011

У меня есть приложение, которое я разрабатываю для iPhone.Что он делает, это захватывает видео с камеры и сохраняет видеофайл в файловой системе.

Мне нужно создать миниатюру этого видео-файла, прежде чем я сохраню его в файловую систему.Мой мотив состоит в том, чтобы показать список миниатюр созданного видео, чтобы пользователь мог выбрать конкретную миниатюру для воспроизведения нужного файла.

Может кто-нибудь посоветует, как создать миниатюрное изображение видеофайла?который был захвачен камерой.

Кроме того, не могли бы вы сообщить, могу ли я создать эскиз существующего видеофайла с помощью iOS SDK.

Ответы [ 5 ]

32 голосов
/ 21 мая 2012

Лучшее решение на самом деле заключается в использовании инфраструктуры AVFoundation для этого. Он обходит необходимость создания MPMoviePlayerController, который вызывает проблему, заключающуюся в том, что радужная оболочка камеры остается закрытой, если используется в сочетании с UIImagePickerController (по крайней мере, это то, что я испытал).

Код, который я использую:

+ (UIImage *)thumbnailFromVideoAtURL:(NSURL *)contentURL {
    UIImage *theImage = nil;
    AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:contentURL options:nil];
    AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
    generator.appliesPreferredTrackTransform = YES;
    NSError *err = NULL;
    CMTime time = CMTimeMake(1, 60);
    CGImageRef imgRef = [generator copyCGImageAtTime:time actualTime:NULL error:&err];

    theImage = [[[UIImage alloc] initWithCGImage:imgRef] autorelease];

    CGImageRelease(imgRef);
    [asset release];
    [generator release];

    return theImage;
}
18 голосов
/ 22 июня 2011

Попробуйте это (на самом деле это не показывает проигрыватель фильмов):

+ (UIImage *)imageFromMovie:(NSURL *)movieURL atTime:(NSTimeInterval)time {
  // set up the movie player
  MPMoviePlayerController *mp = [[MPMoviePlayerController alloc] 
    initWithContentURL:movieURL];
  mp.shouldAutoplay = NO;
  mp.initialPlaybackTime = time;
  mp.currentPlaybackTime = time;
  // get the thumbnail
  UIImage *thumbnail = [mp thumbnailImageAtTime:time 
                           timeOption:MPMovieTimeOptionNearestKeyFrame];
  // clean up the movie player
  [mp stop];
  [mp release];
  return(thumbnail);
}

Предполагается, что это синхронный вызов, поэтому он может блокировать некоторые основные потоки, но, кажется, работает довольно быстродля меня, когда я использую время в начале фильма.Если вы делаете это много, вы можете добавить его в качестве категории на UIImage, что я и сделал.

Я вижу из вашего вопроса, что вы хотите сделать это до сохранения фильма, и ядумаю, это может не работать без файла URL.Однако, если вы используете UIImagePickerController для захвата камеры, вы можете передать этой функции URL-адрес, возвращаемый в информационном словаре imagePickerController: didFinishPickingMediaWithInfo: с ключом UIImagePickerControllerMediaURL.

3 голосов
/ 16 апреля 2014

Очень просто попробуйте это ...

Шаг 1 : заголовок импорта #import <MediaPlayer/MediaPlayer.h>

Шаг 2 : Получить путь к URL

NSURL *videoURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"Sample" ofType:@"m4v"]];

Шаг 3 : наконец получить миниатюру

- (UIImage *)VideoThumbNail:(NSURL *)videoURL
{
    MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:videoURL];
    UIImage *thumbnail = [player thumbnailImageAtTime:52.0 timeOption:MPMovieTimeOptionNearestKeyFrame];
    [player stop];
    return thumbnail;
}
0 голосов
/ 14 ноября 2016

Код для решения, которое использует AVFoundation framework и Swift 3.0 (закомментированный код не нужен и обсуждается ниже кода - вы должны решить, нужен он вам или нет):

import AVFoundation

func generateThumbnailForVideo(at url: URL) -> UIImage? {
    let kPreferredTimescale: Int32 = 1000
    let asset = AVURLAsset(url: url)
    let generator = AVAssetImageGenerator(asset: asset)
    generator.appliesPreferredTrackTransform = true
    //generator.requestedTimeToleranceBefore = kCMTimeZero
    //generator.requestedTimeToleranceAfter = kCMTimeZero
    //generator.maximumSize = CGSize(width: 100, height: 100)

    var actualTime: CMTime = CMTime(seconds: 0, preferredTimescale: kPreferredTimescale)
    //generates thumbnail at first second of the video
    let cgImage = try? generator.copyCGImage(at: CMTime(seconds: 1, preferredTimescale: kPreferredTimescale), actualTime: &actualTime)
    return cgImage.flatMap() { return UIImage(cgImage: $0, scale: UIScreen.main.scale, orientation: .up) }
}

Обратите внимание, что вы можете подумать о запуске этого кода в фоновом потоке, так как создание миниатюр может быть дорогостоящей операцией.

Кроме того, обратите внимание на некоторые свойства класса AVAssetImageGenerator:

  1. requestedTimeToleranceBefore ( документация Apple ):

Максимальная продолжительность до запрашиваемого времени, в течение которого может быть сгенерировано изображение.

Значением по умолчанию является kCMTimePositiveInfinity.

Установите значения значения selectedTimeToleranceBefore и requiredTimeToleranceAfter для kCMTimeZero, чтобы запросить генерацию изображения с точностью до кадра;это может повлечь дополнительную задержку декодирования.

requestedTimeToleranceAfter ( документация Apple ):

Максимальный промежуток времени после запрошенного времени, в течение которого может быть сгенерировано изображение.

Значением по умолчанию является kCMTimePositiveInfinity.

Установите значения значения selectedTimeToleranceBefore и requiredTimeToleranceAfter для kCMTimeZero, чтобы запросить генерацию изображения с точностью до кадра;это может повлечь дополнительную задержку декодирования.

maximumSize ( документация Apple ):

Задает максимальные размеры для сгенерированного изображения.

Значением по умолчанию является CGSizeZero, котороезадает немасштабированные размеры актива.

AVAssetImageGenerator масштабирует изображения таким образом, чтобы они помещались в пределах определенной ограничительной рамки.Изображения никогда не масштабируются.Соотношение сторон масштабированного изображения определяется свойством apertureMode.

0 голосов
/ 20 апреля 2015

Попробуйте это:

generate.requestedTimeToleranceBefore = kCMTimeZero;
generate.requestedTimeToleranceAfter = kCMTimeZero;

Необходимо добавить, чтобы получить правильный кадр.

...