Silent output MP4 when using AVAssetReaderHello, I am trying to create an MP4 by obtaining the content from another source MP4. The source MP4 would be read with `AVAssetReader` and the output written with `AVAssetWriter`. I wanted to do partial t

Hello,

I am trying to create an MP4 by obtaining the content from another source MP4.

The source MP4 would be read with AVAssetReader and the output written with AVAssetWriter.

I wanted to do partial tests: first, I placed only the video in the output MP4.

Now, I am trying to place only the audio in the output MP4.

I even managed to get the output MP4 to have the same length (in seconds) as the source MP4.

But the problem is simple: the output MP4 is simply silent.

Naturally, I want it to have audio.

Below are two excerpts from the source code.

  1. Reading and writing.

Note: The variable videoURL is from the class where the function writeVideo() is located. Its assignment happens in another scope, already debugged.

Snippet:

let semaphore = DispatchSemaphore(value: 0)

func writeVideo() {
    var audioReaderBuffers = [CMSampleBuffer]()

    // File directory
    url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("*****/output.mp4")

    guard let url = url else { return }

    try FileManager.default.createDirectory(at: url.deletingLastPathComponent(), withIntermediateDirectories: true)

    if FileManager.default.fileExists(atPath: url.path()) {
        try FileManager.default.removeItem(at: url)
    }

    if let videoURL = videoURL {
        let videoAsset = AVAsset(url: videoURL)
        Task {
            let audioTrack = try await videoAsset.loadTracks(withMediaType: .audio).first!
            let reader = try AVAssetReader(asset: videoAsset)
            let audioSettings = [
                AVFormatIDKey: kAudioFormatLinearPCM,
                AVSampleRateKey: 44100,
                AVNumberOfChannelsKey: 2
            ] as [String : Any]
            let audioOutputTest = try await audioTrack.getAudioSettings()
            let readerAudioOutput = AVAssetReaderTrackOutput(track: audioTrack, outputSettings: audioSettings)
            reader.add(readerAudioOutput)
            reader.startReading()

            while let sampleBuffer = readerAudioOutput.copyNextSampleBuffer() {
                audioReaderBuffers.append(sampleBuffer)
            }
            semaphore.signal()
        }
    }

    semaphore.wait()

    let audioInput = createAudioInput(sampleBuffer: audioReaderBuffers[0])

    let assetWriter = try AVAssetWriter(outputURL: url, fileType: .mp4)

    assetWriter.add(audioInput)
    assetWriter.startWriting()
    assetWriter.startSession(atSourceTime: .zero)

    for (index, buffer) in audioReaderBuffers.enumerated() {
        while !audioInput.isReadyForMoreMediaData {
            usleep(1000)
        }
        audioInput.append(buffer)
    }

    assetWriter.finishWriting {
        switch assetWriter.status {
        case .completed:
            print("Operation completed successfully: \(url.absoluteString)")
        case .failed:
            if let error = assetWriter.error {
                print("Error description: \(error.localizedDescription)")
            } else {
                print("Error not found.")
            }
        default:
            print("Error not found.")
        }
    }
}
  1. Below is the createAudioInput method:
func createAudioInput(sampleBuffer: CMSampleBuffer) -> AVAssetWriterInput {
    let audioSettings = [
        AVFormatIDKey: kAudioFormatMPEG4AAC,
        AVSampleRateKey: 48000,
        AVEncoderBitRatePerChannelKey: 64000,
        AVNumberOfChannelsKey: 1
    ] as [String : Any]

    let audioInput = AVAssetWriterInput(mediaType: .audio, outputSettings: audioSettings, sourceFormatHint: sampleBuffer.formatDescription)

    audioInput.expectsMediaDataInRealTime = false

    return audioInput
}

I await your help, please.

Silent output MP4 when using AVAssetReaderHello, I am trying to create an MP4 by obtaining the content from another source MP4. The source MP4 would be read with `AVAssetReader` and the output written with `AVAssetWriter`. I wanted to do partial t
 
 
Q