是否可以使用 swift 将 Ipod 库中的音乐保存到我的应用程序中?
Is it possible to save a music from the Ipod library into my app with swift?
当用户 select 从 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 正在工作,我 select 歌曲及其播放但我不想播放 song.I 已尝试将音频文件上传到服务器。我在列表音频中使用 MPMedia Picker 视图,当我要 select 音频时,我将上传到服务器 (HTTP),我该怎么做???如何使用 Swift 代码访问媒体库?
从库中选择歌曲后,将您的 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;
}
}
}];
}
改编 Krishna 的答案,它使用 AVAssetExportSession
将 MPMediaItem
保存到文件中,您可以在 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 而不是自某个参考日期以来的秒数来生成临时文件。不过思路基本一样
当用户 select 从 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 正在工作,我 select 歌曲及其播放但我不想播放 song.I 已尝试将音频文件上传到服务器。我在列表音频中使用 MPMedia Picker 视图,当我要 select 音频时,我将上传到服务器 (HTTP),我该怎么做???如何使用 Swift 代码访问媒体库?
从库中选择歌曲后,将您的 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;
}
}
}];
}
改编 Krishna 的答案,它使用 AVAssetExportSession
将 MPMediaItem
保存到文件中,您可以在 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 而不是自某个参考日期以来的秒数来生成临时文件。不过思路基本一样