iOS:在不播放视频的情况下获取视频时长和缩略图

24

我需要获取一个(本地)视频的时长,并且以UIImage的形式访问其单独的帧。到目前为止,我一直在使用MPMoviePlayerController来实现这个功能。

首先,我注册了MPMovieDurationAvailableNotification事件,然后调用prepareToPlay。当收到事件时,我记录了视频的持续时间,然后通过requestThumbnailImagesAtTimes请求帧。

这个方法可以工作,但即使我没有以任何方式将视频添加到视图中(我可以听到背景中播放的音频),视频似乎也会开始播放。

有没有办法在不播放视频的情况下获取视频的时长和帧?


如果您将视频存储在文件系统中,则可以将其作为AVAsset assetWithUrl:访问,返回的AVAsset具有持续时间属性。不过缩略图方面我不太确定。 - geraldWilliam
有关这个问题,您有什么建议:https://stackoverflow.com/questions/47617130/error-getting-same-video-thumbnail-image-every-time-in-swift3-ios/47617794#47617794 - Anand Gautam
4个回答

42

获取时长:

NSURL *sourceMovieURL = [NSURL fileURLWithPath:somePath];
AVURLAsset *sourceAsset = [AVURLAsset URLAssetWithURL:sourceMovieURL options:nil];
CMTime duration = sourceAsset.duration;

获取一帧图像截图:

AVAssetImageGenerator* generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:destinationAsset];

//Get the 1st frame 3 seconds in
int frameTimeStart = 3;
int frameLocation = 1;

//Snatch a frame
CGImageRef frameRef = [generator copyCGImageAtTime:CMTimeMake(frameTimeStart,frameLocation) actualTime:nil error:nil];

确实可以正确获取持续时间,谢谢。但是“抓取帧”时序似乎有点不对。我不得不使用CMTimeMakeWithSeconds(offsetInSeconds,600)。 - George Armhold
什么是frameTime?我看到了frameTimeStart,那应该是frameTime吗? - etayluz

11

您可以像这样迅速入门:swift

func getMediaDuration(url: NSURL!) -> Float64{
    let asset : AVURLAsset = AVURLAsset(URL: url) as AVURLAsset
    let duration : CMTime = asset.duration
    return CMTimeGetSeconds(duration)
}

请查看此链接:https://stackoverflow.com/questions/47617130/error-getting-same-video-thumbnail-image-every-time-in-swift3-ios - Anand Gautam
func getMediaDuration(url: URL) -> Double { let asset : AVURLAsset = AVURLAsset(url: url) as AVURLAsset let duration : CMTime = asset.duration return CMTimeGetSeconds(duration) } - Asad Jamil

6
调用 setShouldAutoPlay:NO 可以解决 MPMoviePlayerController 的问题:
 moviePlayerController = [[MPMoviePlayerController alloc] initWithContentURL: movieURL];
[moviePlayerController setShouldAutoplay:NO];   
[moviePlayerController prepareToPlay];

编辑:我没有得到任何解释就被踩了,但我仍然坚持我的答案。如果你需要使用MPMoviePlayerController,那么这将防止媒体的自动播放,同时允许你按照我最初的问题获取持续时间和缩略图。


还有其他人认为默认将自动播放设置为TRUE有点傻吗? - sunny
1
你的回答确实回答了问题;但我猜测你被踩的原因是你使用 MPMoviePlayerController 的方式是一个丑陋的解决方法,可能会使用比获取所需信息更多的资源,并且在未来的iOS版本中可能会出现问题。你正在要求系统加载到内存并准备播放视频,而你只需要一些关于它的元数据。离题了:只是出于好奇,它是否会显示谁给你点了踩?我从来没有被踩过,所以很好奇。 - Velociround

0
使用这个方法:
class func getVideoInfo(from url: URL,
                        completion: @escaping ((_ image: UIImage?, _ duration: CGFloat?) -> Void)) {
    DispatchQueue.global().async {
        let asset = AVAsset(url: url)
        let duration = CMTimeGetSeconds(asset.duration)
        let avAssetImageGenerator = AVAssetImageGenerator(asset: asset)
        avAssetImageGenerator.appliesPreferredTrackTransform = true
        let thumnailTime = CMTimeMake(value: 2, timescale: 1)
        do {
            let cgThumbImage = try avAssetImageGenerator.copyCGImage(at: thumnailTime, actualTime: nil)
            let thumbNailImage = UIImage(cgImage: cgThumbImage)
            DispatchQueue.main.async {
                completion(thumbNailImage, duration)
            }
        } catch {
            DispatchQueue.main.async {
                completion(nil, nil)
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接