是否可以使用swift将Ipod库中的音乐保存到我的应用程序中?

时间:2016-12-02 04:40:40

标签: ios swift audio-player ituneslibrary

当用户从iPod库中选择音频时,我会引用MPMediaItem。我使用

获取该项目的资产URL
 let url = item.valueForProperty(MPMediaItemPropertyAssetURL)

但这不是给我文件的确切物理位置,相反,它给了我一个URL w.r.t iPod库。

ipod-library://item/item.mp3?id=1840064795502796074

有没有办法从iPod库中获取歌曲的物理URL?

编辑 - 实际上我想从物理文件中提取NSData并将其发送到我的后端服务器,因此我需要物理文件URL而不是相对URL

MPmediaPickerController正在工作,我选择了歌曲及其播放但我不想播放这首歌。我试图将音频文件上传到服务器。我在列表音频中使用MPMedia Picker视图,当我要选择我将上传到服务器(HTTP)的音频时,我该怎么做?如何使用Swift代码访问媒体库?

2 个答案:

答案 0 :(得分:5)

调整Krishna的答案,使用AVAssetExportSessionMPMediaItem保存到文件中,您可以在Swift 3中执行以下操作:

/// Export MPMediaItem to temporary file.
///
/// - Parameters:
///   - assetURL: The `assetURL` of the `MPMediaItem`.
///   - completionHandler: Closure to be called when the export is done. The parameters are a boolean `success`, the `URL` of the temporary file, and an optional `Error` if there was any problem. The parameters of the closure are:
///
///   - fileURL: The `URL` of the temporary file created for the exported results.
///   - error: The `Error`, if any, of the asynchronous export process.

func export(_ assetURL: URL, completionHandler: @escaping (_ fileURL: URL?, _ error: Error?) -> ()) {
    let asset = AVURLAsset(url: assetURL)
    guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else {
        completionHandler(nil, ExportError.unableToCreateExporter)
        return
    }

    let fileURL = URL(fileURLWithPath: NSTemporaryDirectory())
        .appendingPathComponent(NSUUID().uuidString)
        .appendingPathExtension("m4a")

    exporter.outputURL = fileURL
    exporter.outputFileType = "com.apple.m4a-audio"

    exporter.exportAsynchronously {
        if exporter.status == .completed {
            completionHandler(fileURL, nil)
        } else {
            completionHandler(nil, exporter.error)
        }
    }
}

func exampleUsage(with mediaItem: MPMediaItem) {
    if let assetURL = mediaItem.assetURL {
        export(assetURL) { fileURL, error in
            guard let fileURL = fileURL, error == nil else {
                print("export failed: \(error)")
                return
            }

            // use fileURL of temporary file here
            print("\(fileURL)")
        }
    }
}

enum ExportError: Error {
    case unableToCreateExporter
}

或者,在Swift 2中:

/// Export MPMediaItem to temporary file.
///
/// - Parameters:
///   - assetURL: The `assetURL` of the `MPMediaItem`.
///   - completionHandler: Closure to be called when the export is done. The parameters are a boolean `success`, the `URL` of the temporary file, and an optional `Error` if there was any problem. The parameters of the closure are:
///
///   - fileURL: The `URL` of the temporary file created for the exported results.
///   - error: The `Error`, if any, of the asynchronous export process.

func export(assetURL: NSURL, completionHandler: (NSURL?, ErrorType?) -> ()) {
    let asset = AVURLAsset(URL: assetURL)
    guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else {
        completionHandler(nil, ExportError.unableToCreateExporter)
        return
    }

    let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
        .URLByAppendingPathComponent(NSUUID().UUIDString)!
        .URLByAppendingPathExtension("m4a")

    exporter.outputURL = fileURL
    exporter.outputFileType = "com.apple.m4a-audio"

    exporter.exportAsynchronouslyWithCompletionHandler {
        if exporter.status == .Completed {
            completionHandler(fileURL, nil)
        } else {
            completionHandler(nil, exporter.error)
        }
    }
}

func exampleUsage(with mediaItem: MPMediaItem) {
    if let assetURL = mediaItem.assetURL {
        export(assetURL) { fileURL, error in
            guard let fileURL = fileURL where error == nil else {
                print("export failed: \(error)")
                return
            }

            // use fileURL of temporary file here
            print("\(fileURL)")
        }
    }
}

enum ExportError: ErrorType {
    case unableToCreateExporter
}

如您所见,我将其放在临时文件夹而不是Documents文件夹中。此外,我使用UUID而不是自某个引用日期以来生成临时文件的秒数。但这个想法基本相同。

答案 1 :(得分:2)

从库中选择歌曲后,将MPMediaItem对象转换为NSData,并使用多部分表单数据将其上传到服务器。

将MPMediaItem转换为NSData

-( void)mediaItemToData : (MPMediaItem * ) curItem
{
    NSURL *url = [curItem valueForProperty: MPMediaItemPropertyAssetURL];
    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: url options:nil];

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset
                                                                      presetName:AVAssetExportPresetAppleM4A];

    exporter.outputFileType =   @"com.apple.m4a-audio";

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * myDocumentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

    [[NSDate date] timeIntervalSince1970];
    NSTimeInterval seconds = [[NSDate date] timeIntervalSince1970];
    NSString *intervalSeconds = [NSString stringWithFormat:@"%0.0f",seconds];

    NSString * fileName = [NSString stringWithFormat:@"%@.m4a",intervalSeconds];

    NSString *exportFile = [myDocumentsDirectory stringByAppendingPathComponent:fileName];

    NSURL *exportURL = [NSURL fileURLWithPath:exportFile];
    exporter.outputURL = exportURL;

    // do the export
    // (completion handler block omitted)
    [exporter exportAsynchronouslyWithCompletionHandler:
     ^{
         int exportStatus = exporter.status;

         switch (exportStatus)
         {
             case AVAssetExportSessionStatusFailed:
             {
                 NSError *exportError = exporter.error;
                 NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
                 break;
             }
             case AVAssetExportSessionStatusCompleted:
             {
                 NSLog (@"AVAssetExportSessionStatusCompleted");

                 NSData *data = [NSData dataWithContentsOfFile: [myDocumentsDirectory
                                                                 stringByAppendingPathComponent:fileName]];

                 [arrayMusic addObject:data];
                 data = nil;

                 break;
             }
             case AVAssetExportSessionStatusUnknown:
             {
                 NSLog (@"AVAssetExportSessionStatusUnknown"); break;
             }
             case AVAssetExportSessionStatusExporting:
             {
                 NSLog (@"AVAssetExportSessionStatusExporting"); break;
             }
             case AVAssetExportSessionStatusCancelled:
             {
                 NSLog (@"AVAssetExportSessionStatusCancelled"); break;
             }
             case AVAssetExportSessionStatusWaiting:
             {
                 NSLog (@"AVAssetExportSessionStatusWaiting"); break;
             }
             default:
             {
                 NSLog (@"didn't get export status"); break;
             }
         }
     }];

}