sbooth / SFBAudioEngine

A powerhouse of audio functionality for macOS, iOS, and tvOS
https://sbooth.github.io/SFBAudioEngine/
MIT License
570 stars 86 forks source link

Unable to import CSFBAudioEngine #331

Closed Alenroyfeild closed 4 months ago

Alenroyfeild commented 5 months ago

even after importing CSFBAudioEngine, the error is throwing. Due to that unable to use various encoders and decoders.

image

tried by running these commands

Thanks in advance 🙏🏻

sbooth commented 5 months ago

The encoder and decoder subclasses are not public.

You can instantiate a preferred encoder or decoder by name:

https://github.com/sbooth/SFBAudioEngine/blob/320311d2417219ee793603e4b669a2a48feeaa7e/Sources/CSFBAudioEngine/include/SFBAudioEngine/SFBAudioDecoder.h#L117

The README has an example:

let encoder = try AudioEncoder(outputSource: output, encoderName: .coreAudio)
Alenroyfeild commented 5 months ago

need to perform checking the ogg is opus/vorbis and use respective decoder and convert to mp3

can you guide me to implement this?

sbooth commented 5 months ago

Could you explain why the type of decoder matters for your use case?

Alenroyfeild commented 5 months ago

while using this AudioConverter.convert(inputURL, to: outputURL), by default getting this error: The file “3620890624888924.ogg” is not a valid Ogg Vorbis file. But the input file is ogg of opus codec type. SO based on the ogg codec type planning to use respective decoder. SFBOggVorbisDecoder, SFBOggOpusDecoder

Alenroyfeild commented 5 months ago

This is the way i have implemented to check the codec and use respective decoder to convert to mp3

static func convertOggTomp3(fileURL: URL, destFileURL: URL) -> Bool {
        do {
            let decoder: AudioDecoder

            // Get the codec from the OGG file
            guard let codec = getCodecFromOGG(url: fileURL) else {
                logDebug("Failed to get codec from OGG file")
                return false
            }

            // Initialize the decoder based on the codec
            if codec.contains("Ogg Opus") {
                decoder = try AudioDecoder(url: fileURL, decoderName: .oggOpus)
            } else if codec.contains("Ogg Vorbis") {
                decoder = try AudioDecoder(url: fileURL, decoderName: .oggVorbis)
            } else if codec.contains("Ogg Speex") {
                decoder = try AudioDecoder(url: fileURL, decoderName: .oggSpeex)
            } else {
                logDebug("Unsupported OGG codec")
                return false
            }

            let encoder = try AudioEncoder(url: destFileURL, encoderName: .MP3)
            // Initialize the audio converter
            try AudioConverter(decoder: decoder, encoder: encoder)
            return true
        } catch {
            logDebug("Error during conversion: \(error.localizedDescription)")
            return false
        }
    }

    static func getCodecFromOGG(url: URL) -> String? {
        do {
            // Initialize the audio file with the given URL
            let audioFile = try AudioFile(url: url, formatName: .oggOpus)

            // Read properties and metadata
            try audioFile.readPropertiesAndMetadata()

            // Access the properties
            let properties = audioFile.properties
            if let formatName = properties[AudioProperties.Key.formatName] as? String {
                return formatName
            } else {
                logDebug("Format name not found in properties")
            }
        } catch {
            logDebug("Error reading audio file: \(error.localizedDescription)")
        }
        return nil
    }

But the destination file url(MP3 audio) is coming with - Zero bytes

sbooth commented 5 months ago

error: The file “3620890624888924.ogg” is not a valid Ogg Vorbis file.

Thanks for explaining. The lack of file type detection for Ogg streams is a shortcoming in the library.

If you control the file naming using a more specific extension (such as opus) will help. Alternatively, if you know the MIME type setting that will take precedence over extension-based type resolution.

There are also other libraries (such as oggz) that could help with this.

In general transcoding from one lossy format to another is not a good idea, so I wouldn't recommend converting from Opus to MP3.

However, it should work. I don't see an actual call to convert in your code. The line

try AudioConverter(decoder: decoder, encoder: encoder)

creates an AudioConverter and then throws it away without doing anything with it. The compiler should have generated a warning for this: Result of 'AudioConverter' initializer is unused.

sbooth commented 4 months ago

I've created #333 to track this.