2009-11-01 57 views

回答

29

你可以这样的方式获得媒体项目的数据:

-(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只工作,后来

祝你好运!

+0

试试这个代码在ios 4.0中,但它不工作下面是代码的来源 – GhostRider 2010-10-22 07:24:43

+0

这种解决方案是复杂的方式,看看我的下面(你不需要一个导出会话)。 – 2011-04-15 15:58:37

+0

在nsdata中为null – Rajneesh071 2013-04-24 11:42:19

-3

你不能,也没有解决方法。 MPMediaItem不是实际的媒体,它只是关于通过另一个进程通过RPC传递给应用程序的媒体项目的元数据。项目本身的数据在您的地址空间中无法访问。

我应该注意,即使您有MPMediaItem,它的数据可能也没有加载到设备内存中。 iPhone上的闪存很慢,内存很少。尽管Apple可能不希望您访问支持MPMediaItem的原始数据,但他们不打算处理它,因为他们不想投入处理API所需的时间。如果他们确实提供了访问这样的东西,它几乎肯定不会是一个NSData,但更可能作为一个NSURL,他们会给你的应用程序,允许它打开文件和流通过数据。

无论如何,如果你想要的功能,你应该file错误报告要求。

此外,作为一个附注,不要在发送给Apple的错误报告中提及您的年龄。我认为你正在为手机编写应用程序非常酷,当我还是你的年龄时,我喜欢试验电脑(当时我正在研究用Lisp编写的东西)。问题是你无法在美国合法地同意一份合同,这就是为什么开发者协议明确禁止你加入。从agreement第一段:

也证明你是在你(在许多 国家的 年满18岁)居住在 管辖多数 法定年龄的你表示您 被合法许可成为 注册的iPhone开发者。

如果您向WWDR代表提及您不是年龄大的成员,他们可能会意识到您违反了协议并有义务终止您的开发者帐户。只是一个友好的警告。

+3

我父亲在技术上做了所有这些工作,他是iPhone开发人员,所以这一切都很好 – conradev 2009-11-01 13:38:40

+0

在写作时(2009年)可能是正确的。但现在在2017年有一个API,答案至少是过时的(如果2009年是正确的:我不是一个流动历史学家,我不记得在2009年11月是否有AVAssetExportSession) – 2017-06-19 09:36:44

18

当然你可以访问MPMediaItem的数据。这一次不是很清楚,但是它很有效。具体方法如下:

  • 获取媒体项目的URL从它的MPMediaItemPropertyAssetURL财产
  • 初始化一个AVURLAsset这个URL
  • 与此资产
  • 初始化AVAssetReader抓取AVAssetTrack要从AVURLAsset
  • 阅读
  • 在该曲目中创建一个AVAssetReaderTrackOutput
  • 将此输出结果添加到AVAssetReader之前创建和-startReading
  • 获取的所有数据与AVAssetReaderTrackOutput-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; 
} 
+0

你有这种方法的代码示例吗? – coder 2011-12-27 15:56:46

+0

更新了示例代码 – 2011-12-28 14:23:04

+0

@ErikAigner我可以使用Media Picker在nslog中列出歌曲。但我想用我的播放器播放这些歌曲(使用Avplayer编码)。我怎样才能播放这两首歌曲 – NextStep 2013-09-04 11:26:23