Swift开发:如何在macOS平台编辑MP3文件的ID3元数据?
用AVFoundation写入MP3元数据(含封面图)
嘿,作为Swift新手处理MP3元数据确实容易卡壳,我来给你一步步梳理怎么写入「更多信息」里的字段,甚至添加专辑封面,用Apple官方的AVFoundation框架就能搞定~
一、写入基础元数据(标题、艺术家等)
AVFoundation是macOS/iOS处理媒体元数据的官方工具,我们可以通过导出会话来修改元数据,同时保留原音频质量:
import AVFoundation func writeMP3BasicMetadata(to fileURL: URL, title: String, artist: String) throws { // 1. 加载目标MP3文件 let asset = AVURLAsset(url: fileURL) // 2. 创建导出会话(Passthrough模式不重新编码,速度快) guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough) else { throw NSError(domain: "MP3MetadataError", code: 1, userInfo: [NSLocalizedDescriptionKey: "无法创建导出会话"]) } // 3. 设置输出路径(建议先导出为新文件,避免覆盖原文件) let outputURL = fileURL.deletingPathExtension().appendingPathExtension("modified.mp3") // 4. 创建标题元数据项 let titleItem = AVMutableMetadataItem() titleItem.identifier = .commonIdentifierTitle // 对应「更多信息」里的"标题" titleItem.value = title as NSString titleItem.extendedLanguageTag = "und" // 通用语言标签 // 5. 创建艺术家元数据项 let artistItem = AVMutableMetadataItem() artistItem.identifier = .commonIdentifierArtist // 对应「更多信息」里的"艺术家" artistItem.value = artist as NSString artistItem.extendedLanguageTag = "und" // 6. 将元数据添加到导出会话 exportSession.metadata = [titleItem, artistItem] // 7. 配置导出参数并执行 exportSession.outputURL = outputURL exportSession.outputFileType = .mp3 exportSession.exportAsynchronously { switch exportSession.status { case .completed: print("元数据写入成功!新文件:\(outputURL)") // 测试没问题后,可以在这里替换原文件 case .failed: print("导出失败:\(exportSession.error?.localizedDescription ?? "未知错误")") case .cancelled: print("导出被取消") default: break } } }
你可以根据需求添加其他字段,比如专辑名(.commonIdentifierAlbumTitle)、流派(.commonIdentifierGenre)等,这些标识符都对应「更多信息」里的默认选项。
二、添加专辑封面图片
要给MP3添加封面,只需要创建对应artwork的元数据项,把图片转为Data格式即可:
import AVFoundation import AppKit func addMP3AlbumArtwork(to fileURL: URL, coverImage: NSImage) throws { let asset = AVURLAsset(url: fileURL) guard let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetPassthrough) else { throw NSError(domain: "MP3MetadataError", code: 2, userInfo: [NSLocalizedDescriptionKey: "无法创建导出会话"]) } let outputURL = fileURL.deletingPathExtension().appendingPathExtension("with_cover.mp3") // 将NSImage转为JPEG格式数据(MP3封面常用JPEG) guard let tiffData = coverImage.tiffRepresentation, let bitmapRep = NSBitmapImageRep(data: tiffData), let jpegData = bitmapRep.representation(using: .jpeg, properties: [.compressionFactor: 0.8]) else { throw NSError(domain: "MP3MetadataError", code: 3, userInfo: [NSLocalizedDescriptionKey: "图片转换失败"]) } // 创建封面元数据项 let artworkItem = AVMutableMetadataItem() artworkItem.identifier = .commonIdentifierArtwork artworkItem.value = jpegData as NSData artworkItem.extendedLanguageTag = "und" // 保留原有元数据,再添加封面(避免覆盖原有信息) var existingMetadata = exportSession.metadata ?? [] existingMetadata.append(artworkItem) exportSession.metadata = existingMetadata // 执行导出 exportSession.outputURL = outputURL exportSession.outputFileType = .mp3 exportSession.exportAsynchronously { switch exportSession.status { case .completed: print("封面添加成功!新文件:\(outputURL)") case .failed: print("导出失败:\(exportSession.error?.localizedDescription ?? "未知错误")") default: break } } }
三、新手必看注意事项
- 沙箱权限:macOS应用需要获取文件读写权限,建议用
NSOpenPanel让用户选择文件,自动获取权限。 - 不要直接覆盖原文件:先导出为新文件测试,确认没问题后再替换原文件,防止数据丢失。
- 自定义元数据键:如果你之前读取到的是自定义ID3标签键(比如
©nam),可以直接设置item.key = "©nam"替代identifier,不过用通用标识符兼容性更好。 - ID3版本:AVFoundation会自动处理ID3v2.3或v2.4,不需要手动指定版本。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

