当前位置: 首页 > 面试题库 >

迅捷:如何删除部分音频?

申高卓
2023-03-14
问题内容

我正在创建一个简单的音频编辑工具来修剪和删除音频。我实现了修剪功能,并且工作正常。但是我搜索并尝试实现删除功能,这是我的代码

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个范围。从0-> time1的Range1和从time2-> endOfAudio的Range2。(我想从时间1->时间2中删除)

然后我在2个范围之间创建并集。但是,音频没有任何反应。它的保存与该功能之前的保存完全相同。


问题答案:

CMTimeRangeGetUnion返回another
CMTimeRange,它只是一个(开始)时间和一个持续时间。因此,没有什么可以容纳完成您期望的两个时间范围。扩展而言,AVASsetExportSession没有API需要导出时间范围
列表

但是有一种方法可以实现它。这个想法是创建资产的可编辑副本,删除时间范围,然后导出可编辑副本。AVMutableComposition做这个:

// 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
}

请注意,从资产复制到合成仅会修改某些内存结构,这些结构定义了哪些样本在时间轴上到达何处,但实际上并没有移动任何媒体样本。直到导出才完成。结果,编辑(相对)很快,并且您必须至少保留源文件,直到导出完成。



 类似资料:
  • 问题内容: 我正在尝试编写一个快速的iOS应用程序,它将记录用户的声音。我已经迅速编写了以下代码,但是无法从用户那里请求麦克风权限。它可以正常打印,但从不记录音频,并且在“隐私”下的“设置”窗格中未列出该应用程序。如何快速请求录制权限? 问题答案: 从iOS 7开始,您需要检查它是否响应选择器 我已经使用带有 iOS 8 Beta* 的 iPhone 5S 测试了此代码,它可以完美运行。授予权限后

  • 在iOS 15中,在节头和第一个单元格之间添加分隔符: 如何隐藏或删除该分隔符? 几点注意事项 标题是从 查看视图调试器时,我可以看到额外的分隔符实际上是第一个单元格的子视图,它现在有一个顶部分隔符和一个底部分隔符。 除了设置更改单元格分隔符的插入外,这是一个完全标准的表视图,没有任何自定义设置

  • 问题内容: 我有一些简单的python代码,可在文件中搜索字符串,例如,其中部分可能会有所不同。当前代码是: 什么是获取文字的简单方法? 问题答案: 从开始,您可以使用:

  • 问题内容: 当SQL数据类型为时间戳时,java.util.Date将存储为2010-09-03 15:33:22.246,在存储记录之前,如何将子秒设置为零(例如,本例中为246)。 问题答案: 这是一个主意:

  • 问题内容: 我有一段代码会生成很多警告(不推荐使用的API) 使用clang *我可以做 但是,这并不迅速。 如何迅速进行? 注意:我不想全局禁用警告,甚至不想禁用整个文件,而只是在源代码的特定部分禁用特定警告。 编辑:我看起来我的笔记不够清楚:我不希望条件编译(这是假定重复的建议答案)。我只想在不使用新API的情况下使警告静音。 问题答案: 截至2019年,Xcode 11.0一直没有办法实现这

  • 问题内容: 我有一个要删除的带有孩子的小部件。我怎么做?我找不到任何,,或任何类似的文档。我只能看到如何从布局中删除内容,但是显然,它并没有从实际的窗口小部件中删除它。 问题答案: 好吧,这可行:在要删除的小部件上,调用。我喜欢添加到布局中的方式,将小部件添加到容器中,但是从布局中删除则不…有趣的东西。