swift:如何删除部分音频? [英] swift: how to delete part of audio?
问题描述
我正在创建一个简单的音频编辑工具来修剪和删除音频.我实现了修剪功能,它工作正常.但是我搜索并尝试实现删除功能,这是我的代码:
I'm creating a simple audio editing tool to trim and delete from an audio. I implemented the trim function and it is working fine. However I searched and tried to implement the delete function and here is my code:
func deleteExportAsset(_ asset: AVAsset, fileName: String, completeAudioTime: CGFloat) -> URL {
print("(#function)")
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let trimmedSoundFileURL = documentsDirectory.appendingPathComponent(fileName)
print("saving to (trimmedSoundFileURL.absoluteString)")
if FileManager.default.fileExists(atPath: trimmedSoundFileURL.absoluteString) {
print("sound exists, removing (trimmedSoundFileURL.absoluteString)")
do {
if try trimmedSoundFileURL.checkResourceIsReachable() {
print("is reachable")
}
try FileManager.default.removeItem(atPath: trimmedSoundFileURL.absoluteString)
} catch {
print("could not remove (trimmedSoundFileURL)")
print(error.localizedDescription)
}
}
print("creating export session for (asset)")
if let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) {
exporter.outputFileType = AVFileType.m4a
exporter.outputURL = trimmedSoundFileURL
let timeRange1 = CMTimeRangeFromTimeToTime(CMTime(seconds: 0, preferredTimescale: 100), CMTime(seconds: endTimeOfRange1, preferredTimescale: 100))
let timeRange2 = CMTimeRangeFromTimeToTime(CMTime(seconds: startTimeOfRange2)), preferredTimescale: 100), CMTime(seconds: Double(completeAudioTime), preferredTimescale: 100))
exporter.timeRange = CMTimeRangeGetUnion(timeRange1, timeRange2)
// do it
exporter.exportAsynchronously(completionHandler: {
print("export complete (exporter.status)")
switch exporter.status {
case AVAssetExportSessionStatus.failed:
if let e = exporter.error {
print("export failed (e)")
}
case AVAssetExportSessionStatus.cancelled:
print("export cancelled (String(describing: exporter.error))")
default:
print("export complete")
}
})
} else {
print("cannot create AVAssetExportSession for asset (asset)")
}
return trimmedSoundFileURL
}
我在这里做的是创建 2 个范围.Range1 从 0 ->time1 和 Range2 从 time2->endOfAudio.(我想从time1->time2删除)
what I'm doing here is creating 2 Ranges. Range1 from 0 ->time1 and Range2 from time2->endOfAudio. (I want to delete from time1 -> time2)
然后我正在创建 2 个范围之间的联合.但是,音频没有发生任何变化.它的保存方式与此功能之前完全相同.
then I'm creating the union between 2 ranges. however, nothing is happening to the audio. It is saved exactly like it was before this function.
推荐答案
CMTimeRangeGetUnion
返回另一个 CMTimeRange
,它只是一个(开始)时间和一个持续时间.因此,没有什么可以保持执行您期望的操作所需的两个时间范围.在扩展中,AVAssetExportSession 没有需要导出时间范围列表的 API.
CMTimeRangeGetUnion
returns another CMTimeRange
, which is just a (start-)time and a duration. So there is nothing than can hold the two time ranges required to do what you are expecting. In extension, AVAssetExportSession has no API that takes a list of time ranges to export.
但是有一种方法可以实现它.想法是创建资产的可编辑副本,删除时间范围,然后导出可编辑副本.AVMutableComposition
这样做:
But there is a way to accomplish it. The idea is to create an editable copy of the asset, delete the time range, and then export the editable copy. AVMutableComposition
does this:
// assuming 'asset', 'endTimeOfRange1' and 'startTimeOfRange2' from the question:
// create empty mutable composition
let composition: AVMutableComposition = AVMutableComposition()
// copy all of original asset into the mutable composition, effectively creating an editable copy
try composition.insertTimeRange( CMTimeRangeMake( kCMTimeZero, asset.duration), of: asset, at: kCMTimeZero)
// now edit as required, e.g. delete a time range
let startTime = CMTime(seconds: endTimeOfRange1, preferredTimescale: 100)
let endTime = CMTime(seconds: startTimeOfRange2, preferredTimescale: 100)
composition.removeTimeRange( CMTimeRangeFromTimeToTime( startTime, endTime))
// since AVMutableComposition is an AVAsset subclass, it can be exported with AVAssetExportSession (or played with an AVPlayer(Item))
if let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
{
// configure session and exportAsynchronously as above.
// You don't have to set the timeRange of the exportSession
}
请注意,从资产复制到合成只会修改一些内存中的结构,这些结构定义了哪些样本在时间线上的位置,但实际上并没有移动任何媒体样本.这直到导出才完成;因此,编辑(相对)很快,并且您必须至少在导出完成之前保留源文件.
Note that copying from the asset to the composition only modifies some in-memory structures defining which samples go where on the time line, but doesn't actually moves any media samples around. This is not done until exporting; as result, editing is (relatively) fast, and you have to keep the source file around at least until export is finished.
这篇关于swift:如何删除部分音频?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!