【问题标题】:Extract audio from video file从视频文件中提取音频
【发布时间】:2012-07-10 23:54:47
【问题描述】:

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

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

【问题讨论】:

  • 据我所知,iOS 上的 AVFoundation 对于如何解码或打开“.flv”文件一无所知,所以这个问题一开始就不是初学者。这就是为什么您需要使用一些第三方库(例如 ffmpeg 或其他库)来打开 .flv 文件并将其转换为您可以正确使用的东西。
  • 我将编辑示例,因为我没有考虑这一点......但我的要求仍然是一样的...... :(

标签: iphone ios video avmutablecomposition avurlasset


【解决方案1】:

以下 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)
            }
        }
    }

}

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 感谢您的回答.. +1 给它.. 但如果你能在编码部分帮助我.. 那将是一个很大的帮助:)
    • Sorry... MOV(类似于 MP4)是一种复杂的文件格式,编写这样的解析器至少需要一两天的编码,所以我无法帮助您。我猜你最初尝试用 AVMutableComposition 来做这件事的想法是一个更好的方法(它应该做同样的事情) - 基本上 M4A 文件几乎类似于没有音轨的 MOV,所以将 MOV 作为 AVMutableComposition 打开并执行 removeTrack可能会成功......
    • @onon15 - (+1) 我有一个包含 1 个音频 TRAK 和 1 个视频 TRAK(aac,h264)的文件,我如何区分“mdat”原子中的样本?谢谢!
    • 这并不像你想象的那么容易,但一旦你掌握了窍门,它并不难。 您无法从 MDAT 本身获取它。属于每个轨道的数据块的偏移量存储在TRAK>MDIA>MINF>STBL 内部的STCO 表(或CO64)中。每个块的长度是您需要对STBL 中的信息进行的另一个计算。见this reference
    猜你喜欢
    • 1970-01-01
    • 2020-03-26
    • 2012-12-12
    • 2010-10-09
    • 2020-06-26
    • 1970-01-01
    • 2018-01-29
    相关资源
    最近更新 更多