iOS音频元数据读取与编辑技术问询(含AVMetadataItem问题)
嘿,刚好我之前处理过类似的音频元数据场景,来帮你逐个梳理这些问题:
1. 有没有相关的官方文档?
当然有!苹果的AVFoundation框架文档里专门有元数据相关的章节,重点看AVMetadataItem、AVAssetMetadata的官方说明,里面会提到commonKey和格式特定key的区别。另外你看到的TPE1、TRCK这些是ID3标签的帧标识,苹果文档里也有对应映射表,比如TPE1对应AVMetadataKey.commonKeyArtist,TRCK对应AVMetadataID3MetadataKeyTrackNumber。
2. 为什么会有commonKey为nil的项,是不是遗漏了什么?
你遇到的情况很常见:苹果的commonKey是对不同格式元数据(比如ID3、iTunes Metadata)的统一封装,但有些元数据项可能因为文件格式、编辑工具(比如iTunes)的写法,没有被自动映射到commonKey,这时候就需要直接检查格式特定的key。
比如你要找的曲目编号1/2,对应的是ID3的TRCK帧,你可以通过以下方式获取:
for metadataItem in audioAsset.metadata { // 检查commonKey的逻辑保留 if metadataItem.commonKey == AVMetadataKey.commonKeyArtist { print("artistName IN METADATA \(metadataItem.value)") } // 检查ID3格式的曲目编号key if metadataItem.identifier == AVMetadataIdentifier.id3MetadataTrackNumber { if let trackValue = metadataItem.value as? String { print("Track number: \(trackValue)") // 这里就能拿到1/2啦 } } // 极端情况:如果上面的identifier没匹配到,直接检查原始ID3帧标识 if metadataItem.key as? String == "TRCK" { // 同样可以获取曲目编号 } }
3. 编辑元数据的最佳方式是什么?
AVAsset本身是只读的,所以要修改元数据并持久化到文件,需要通过AVAssetExportSession导出新文件的方式,步骤大概是:
- 把原Asset的元数据复制为可变数组(
AVMutableMetadataItem) - 创建或修改对应的元数据项,设置正确的key、value、标识符等
- 配置导出会话,把修改后的元数据传入,导出到新文件
举个修改曲目编号的例子:
// 1. 复制原元数据为可变数组 var mutableMetadata = audioAsset.metadata.map { $0.copy() as! AVMutableMetadataItem } // 2. 创建新的曲目编号元数据项 let trackItem = AVMutableMetadataItem() trackItem.key = AVMetadataID3MetadataKeyTrackNumber as NSString trackItem.value = "1/2" as NSString trackItem.locale = Locale.current trackItem.identifier = AVMetadataIdentifier.id3MetadataTrackNumber trackItem.extendedLanguageTag = "und" // 通用语言标识 // 3. 替换原有曲目编号(如果存在),否则添加 if let existingIndex = mutableMetadata.firstIndex(where: { $0.identifier == AVMetadataIdentifier.id3MetadataTrackNumber }) { mutableMetadata[existingIndex] = trackItem } else { mutableMetadata.append(trackItem) } // 4. 导出新文件 guard let exportSession = AVAssetExportSession(asset: audioAsset, presetName: AVAssetExportPresetPassthrough) else { print("Failed to create export session") return } exportSession.outputURL = URL(fileURLWithPath: "/path/to/your/output/file.mp3") // 替换成你的输出路径 exportSession.outputFileType = audioAsset.preferredExportFileType exportSession.metadata = mutableMetadata exportSession.exportAsynchronously { switch exportSession.status { case .completed: print("Metadata updated successfully!") // 这里可以处理新生成的文件 case .failed, .cancelled: print("Export error: \(exportSession.error?.localizedDescription ?? "Unknown error")") default: break } }
注意:不同音频格式对应的元数据key不一样,比如M4A文件用的是iTunes Metadata,对应的曲目编号key是AVMetadataKey.itunesMetadataKeyTrackNumber,导出时要匹配文件格式选择正确的key。
4. 在编辑文件的UIViewController中能否添加元数据值?
完全可以!你只需要在UI里收集用户输入的信息(比如曲目编号、艺术家名等),然后按照上面的编辑流程,把用户输入的内容转换成对应的AVMutableMetadataItem,再执行导出操作就行。比如在VC里添加一个输入框让用户输入曲目编号,点击保存按钮时触发元数据修改和导出逻辑。
内容的提问来源于stack exchange,提问作者Reimond Hill

