我想知道如何访问 MPMediaItem 的原始数据。
有任何想法吗?
您可以通过以下方式获取媒体项目的数据:
-(void)mediaItemToData
{
// Implement in your project the media item picker
MPMediaItem *curItem = musicPlayer.nowPlayingItem;
NSURL *url = [curItem valueForProperty: MPMediaItemPropertyAssetURL];
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: url options:nil];
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset
presetName: AVAssetExportPresetPassthrough];
exporter.outputFileType = @"public.mpeg-4";
NSString *exportFile = [[self myDocumentsDirectory] stringByAppendingPathComponent:
@"exported.mp4"];
NSURL *exportURL = [[NSURL fileURLWithPath:exportFile] retain];
exporter.outputURL = exportURL;
// do the export
// (completion handler block omitted)
[exporter exportAsynchronouslyWithCompletionHandler:
^{
NSData *data = [NSData dataWithContentsOfFile: [[self myDocumentsDirectory]
stringByAppendingPathComponent: @"exported.mp4"]];
// Do with data something
}];
}
此代码仅适用于 ios 4.0 及更高版本
祝你好运!
当然你可以访问 a 的数据MPMediaItem
。它不是很清楚,但它确实有效。就是这样:
MPMediaItemPropertyAssetURL
属性中获取媒体项目的 URLAVURLAsset
用这个 URL初始化一个AVAssetReader
用这个资产初始化一个AVAssetTrack
_AVURLAsset
AVAssetReaderTrackOutput
用这个轨道创建一个AVAssetReader
之前创建的和-startReading
AVAssetReaderTrackOutput
用's获取所有数据-copyNextSampleBuffer
这是我的一个项目中的一些示例代码(这不是我的代码宝石,是在我的编码黑暗时代写的):
typedef enum {
kEDSupportedMediaTypeAAC = 'aac ',
kEDSupportedMediaTypeMP3 = '.mp3'
} EDSupportedMediaType;
- (EDLibraryAssetReaderStatus)prepareAsset {
// Get the AVURLAsset
AVURLAsset *uasset = [m_asset URLAsset];
// Check for DRM protected content
if (uasset.hasProtectedContent) {
return kEDLibraryAssetReader_TrackIsDRMProtected;
}
if ([uasset tracks] == 0) {
DDLogError(@"no asset tracks found");
return AVAssetReaderStatusFailed;
}
// Initialize a reader with a track output
NSError *err = noErr;
m_reader = [[AVAssetReader alloc] initWithAsset:uasset error:&err];
if (!m_reader || err) {
DDLogError(@"could not create asset reader (%i)\n", [err code]);
return AVAssetReaderStatusFailed;
}
// Check tracks for valid format. Currently we only support all MP3 and AAC types, WAV and AIFF is too large to handle
for (AVAssetTrack *track in uasset.tracks) {
NSArray *formats = track.formatDescriptions;
for (int i=0; i<[formats count]; i++) {
CMFormatDescriptionRef format = (CMFormatDescriptionRef)[formats objectAtIndex:i];
// Check the format types
CMMediaType mediaType = CMFormatDescriptionGetMediaType(format);
FourCharCode mediaSubType = CMFormatDescriptionGetMediaSubType(format);
DDLogVerbose(@"mediaType: %s, mediaSubType: %s", COFcc(mediaType), COFcc(mediaSubType));
if (mediaType == kCMMediaType_Audio) {
if (mediaSubType == kEDSupportedMediaTypeAAC ||
mediaSubType == kEDSupportedMediaTypeMP3) {
m_track = [track retain];
m_format = CFRetain(format);
break;
}
}
}
if (m_track != nil && m_format != NULL) {
break;
}
}
if (m_track == nil || m_format == NULL) {
return kEDLibraryAssetReader_UnsupportedFormat;
}
// Create an output for the found track
m_output = [[AVAssetReaderTrackOutput alloc] initWithTrack:m_track outputSettings:nil];
[m_reader addOutput:m_output];
// Start reading
if (![m_reader startReading]) {
DDLogError(@"could not start reading asset");
return kEDLibraryAssetReader_CouldNotStartReading;
}
return 0;
}
- (OSStatus)copyNextSampleBufferRepresentation:(CMSampleBufferRepresentationRef *)repOut {
pthread_mutex_lock(&m_mtx);
OSStatus err = noErr;
AVAssetReaderStatus status = m_reader.status;
if (m_invalid) {
pthread_mutex_unlock(&m_mtx);
return kEDLibraryAssetReader_Invalidated;
}
else if (status != AVAssetReaderStatusReading) {
pthread_mutex_unlock(&m_mtx);
return kEDLibraryAssetReader_NoMoreSampleBuffers;
}
// Read the next sample buffer
CMSampleBufferRef sbuf = [m_output copyNextSampleBuffer];
if (sbuf == NULL) {
pthread_mutex_unlock(&m_mtx);
return kEDLibraryAssetReader_NoMoreSampleBuffers;
}
CMSampleBufferRepresentationRef srep = CMSampleBufferRepresentationCreateWithSampleBuffer(sbuf);
if (srep && repOut != NULL) {
*repOut = srep;
}
else {
DDLogError(@"CMSampleBufferRef corrupted");
EDCFShow(sbuf);
err = kEDLibraryAssetReader_BufferCorrupted;
}
CFRelease(sbuf);
pthread_mutex_unlock(&m_mtx);
return err;
}
你不能,也没有解决方法。MPMediaItem 不是实际的媒体片段,它只是有关媒体项的元数据,通过 RPC 从另一个进程传递给应用程序。在您的地址空间中无法访问项目本身的数据。
我应该注意,即使您拥有 MPMediaItem,它的数据也可能不会加载到设备内存中。iPhone 上的闪存很慢,而且内存不足。虽然 Apple 可能不希望您访问支持 MPMediaItem 的原始数据,但很可能他们没有费心处理它,因为他们不想投入必要的时间来处理 API。如果他们确实提供了对这样的东西的访问,那么它几乎肯定不会是一个 NSData,但更有可能是一个 NSURL,他们会给你的应用程序允许它打开文件并流式传输数据。
无论如何,如果你想要这个功能,你应该提交一份错误报告来要求。
另外,作为旁注,不要在您发送给 Apple 的错误报告中提及您的年龄。我认为你为手机编写应用程序非常酷,当我像你这个年纪时,我喜欢用电脑做实验(当时我正在研究用 Lisp 编写的东西)。问题是你不能在美国合法地同意合同,这就是开发者协议明确禁止你加入的原因。从协议的第一段开始:
您还证明您已达到您居住的司法管辖区的法定成年年龄(在许多国家/地区至少为 18 岁),并且您声明您在法律上被允许成为注册 iPhone 开发者。
如果您向 WWDR 代表提及您未达到成年年龄,他们可能会意识到您违反了协议并有义务终止您的开发者帐户。只是一个友好的警告。