7

如何在不使用 FFmpeg的情况下从视频文件中提取音频?

我想使用AVMutableCompositionAVURLAsset解决它。例如从 .mov 到 .m4a 文件的转换。

4

2 回答 2

12

以下 Swift 5 / iOS 12.3 代码展示了如何从电影文件 ( .mov ) 中提取音频并使用,和将其转换为音频文件 ( .m4a ) :AVURLAssetAVMutableCompositionAVAssetExportSession

import UIKit
import AVFoundation

class ViewController: UIViewController {

    @IBAction func extractAudioAndExport(_ sender: UIButton) {
        // Create a composition
        let composition = AVMutableComposition()
        do {
            let sourceUrl = Bundle.main.url(forResource: "Movie", withExtension: "mov")!
            let asset = AVURLAsset(url: sourceUrl)
            guard let audioAssetTrack = asset.tracks(withMediaType: AVMediaType.audio).first else { return }
            guard let audioCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid) else { return }
            try audioCompositionTrack.insertTimeRange(audioAssetTrack.timeRange, of: audioAssetTrack, at: CMTime.zero)
        } catch {
            print(error)
        }

        // Get url for output
        let outputUrl = URL(fileURLWithPath: NSTemporaryDirectory() + "out.m4a")
        if FileManager.default.fileExists(atPath: outputUrl.path) {
            try? FileManager.default.removeItem(atPath: outputUrl.path)
        }

        // Create an export session
        let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough)!
        exportSession.outputFileType = AVFileType.m4a
        exportSession.outputURL = outputUrl

        // Export file
        exportSession.exportAsynchronously {
            guard case exportSession.status = AVAssetExportSession.Status.completed else { return }

            DispatchQueue.main.async {
                // Present a UIActivityViewController to share audio file
                guard let outputURL = exportSession.outputURL else { return }
                let activityViewController = UIActivityViewController(activityItems: [outputURL], applicationActivities: [])
                self.present(activityViewController, animated: true, completion: nil)
            }
        }
    }

}
于 2017-04-25T00:51:44.293 回答
4

在所有多媒体格式中,音频与视频是分开编码的,它们的帧在文件中交错。因此,从多媒体文件中删除视频不需要对编码器和解码器造成任何干扰:您可以编写一个文件格式解析器来删除视频轨道,而无需使用手机上的多媒体 API。

要在不使用 3rd 方库的情况下做到这一点,您需要从头开始编写解析器,这可能很简单,也可能很困难,具体取决于您希望使用的文件格式。例如,FLV 非常简单,因此从中剥离轨道非常容易(只需遍历流,检测帧开始并丢弃 '0x09'=video 帧)。MP4 稍微复杂一点,它的标题 (MOOV) 具有分层结构,其中每个轨道 (TRAK 原子) 都有标题。您需要删除视频 TRAK,然后复制交错比特流原子 (MDAT),在复制时跳过所有视频数据簇。

除了 ffmpeg,您还可以使用第三方库。想到的一个是 GPAC MP4BOX(LGPL 许可证)。如果 LGPL 有问题,您可以使用很多商业 SDK。

于 2012-07-24T08:03:11.910 回答