我是iOS开发的初学者。我正在开发一个应用程序,我需要在MPMoviePlayerController中播放视频的大小。
我正在使用MPMoviePlayerController的属性naturalSize来获取播放视频的尺寸。
@property(nonatomic, readonly) CGSize naturalSize;
但问题是,只有当视频在MPMoviePlayerController中播放时,我才能获得自然大小。
有没有一种方法可以在MPMoviePlayerController播放之前获取视频的尺寸。
- 编辑 -
我可以采取任何其他解决方法来解决这个问题吗?请帮忙。
MPMoviePlayerController加载视频元数据需要一些时间,因此您应该添加一个侦听器并等待加载naturalSize。像这样的东西:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(movieNaturalSizeAvailable:)
name:MPMovieNaturalSizeAvailableNotification
object:myMoviePlayer];
在movieNaturalSizeAvailable:
,myVideoPlayer.naturalSize
为您提供所需的价值,之后,您可以播放视频。
您可以使用AVURLAsset
和AVAssetTrack
阅读视频的尺寸,如下所示:
NSURL *mediaURL; // Your video's URL
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:mediaURL options:nil];
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
AVAssetTrack *track = [tracks objectAtIndex:0];
然后使用AVAssetTrack
的naturalSize属性:
CGSize mediaSize = track.naturalSize;
以这种方式获取视频元数据的好处是您可以立即访问它,而无需播放视频或等待加载视频。
我想我会分享那些找到这个页面的人的经历。
自然尺寸实际上不是编码分辨率,而是显示分辨率。这可以与编码分辨率不同,例如,如果像素纵横比!= 1或(更常见),则在编码视频中存在干净的孔径元数据信息。
要获得编码分辨率,我发现的唯一方法是使用例如AVASsetReaderTrackOutput解码第一帧,然后使用CVPixelBufferGetWidth(或GetHeight)检查结果像素缓冲区以获得数据分辨率。如果您使用imageGenerator,您将获得显示分辨率(以及显示分辨率的rgb位图)
这是一个老问题,但它是谷歌搜索结果中的第一个。
“naturalSize”属性似乎不是解决方案;在我的测试中,它看起来更像是宽高比。例如,我经常看到naturalSize.height = 9和naturalSize.width = 16
这里有一些代码来获取像素的尺寸,这可能是你想要的,以及其他一些东西。
// in a header file, perhaps
typedef struct VideoInfo {
size_t width;
size_t height;
CGFloat durationInSeconds;
CGFloat framesPerSecond;
} VideoInfo;
+ (VideoInfo) getVideoInfoFromUrl:(NSURL*)fileUrl
{
VideoInfo vidInfo;
vidInfo.width = vidInfo.height = 0;
vidInfo.durationInSeconds = vidInfo.framesPerSecond = 0;
@try {
// get duration and fps
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileUrl options:nil];
vidInfo.durationInSeconds = CMTimeGetSeconds(asset.duration);
vidInfo.framesPerSecond = track.nominalFrameRate;
// get width and height in pixels
// you have to extract a frame from the video and get the dimensions from the frame
AVAsset *avasset = [AVAsset assetWithURL:fileUrl];
AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:avasset error:&error];
if (assetReader) {
NSArray<AVAssetTrack*> *tracks = [avasset tracksWithMediaType:AVMediaTypeVideo];
if (tracks && tracks.count > 0) {
AVAssetTrack* track = [tracks objectAtIndex:0];
NSDictionary *settings = @{(__bridge NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)};
trackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:settings];
[assetReader addOutput:trackOutput];
[assetReader startReading];
CMSampleBufferRef sampleBuffer = [trackOutput copyNextSampleBuffer];
if (sampleBuffer) {
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
if (imageBuffer && (CFGetTypeID(imageBuffer) == CVPixelBufferGetTypeID())) {
// note on iOS, CVImageBufferRef and CVPixelBufferRef are synonyms via:
// typedef CVImageBufferRef CVPixelBufferRef;
CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
vidInfo.height = CVPixelBufferGetHeight(imageBuffer);
vidInfo.width = CVPixelBufferGetWidth(imageBuffer);
CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
CFRelease(imageBuffer);
}
}
}
}
}
}
@catch (NSException *exception) {
}
return vidInfo;
}