BouncedBy
BouncedBy

Reputation: 11

How to bypass system volume on audio player?

How can I ignore the system volume so that when an MP3 is played and, for example, the iPhone's volume is set to 5%, the AudioPlayer's volume is always at 100%?

Currently, the Audio Player adjusts to the iPhone's media volume!

func playProgressTone() {
    guard let soundURL = Bundle.main.url(forResource: "ProgressTone", withExtension: "mp3") else {
        print("Error: Audio file 'ProgressTone.mp3' not found.")
        return
    }

    do {
        progressTonePlayer = try AVAudioPlayer(contentsOf: soundURL)
        progressTonePlayer?.volume = 5.0
        progressTonePlayer?.numberOfLoops = -1 // Repeat until the call is connected

        // Delay of 1.0 seconds before playing the sound
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak progressTonePlayer] in
            progressTonePlayer?.play()
            print("Progress tone will play after 1 second.")
        }

    } catch let error as NSError {
        print("Error playing the progress tone: \(error.localizedDescription)")
    }
}

Upvotes: 0

Views: 61

Answers (1)

SomeUser
SomeUser

Reputation: 56

Hi,

One possibility is with the MediaPlayer framework.

First you create an Extension for the MPVolumeView so that you can control the volume more easily.

Volume is always passed as a Float.

Reason: DRY = Don't Repeat Yourself

1. MPVolumeView Extension:

extension MPVolumeView {
    static func setVolume(_ volume: Float) {
        let volumeView = MPVolumeView()
        let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            slider?.value = volume
        }
    }
}

2. Functions

To make it easier, I have created 2 functions, you could integrate it into your function, for example.

  1. useCustomVolume(): with this we save the current system volume in a state var (state variable) and then set the system Volume to 100%.
func useCustomVolume() {
    systemVolume = Float(AVAudioSession.sharedInstance().outputVolume)
    MPVolumeView.setVolume(Float(1.0))
}
  1. useSystemVolume(): here we now take the saved volume from the State Variable and restore it.
func useSystemVolume() {
    MPVolumeView.setVolume(systemVolume)
}

3. TL;DR Here is an example, using a View:

import SwiftUI
import MediaPlayer

struct ContentView: View {
    
    @State private var systemVolume: Float = 0.0
    @State private var usesCustomVolume: Bool = false
    
    var body: some View {
        VStack {
            
            Text("systemVolume: \(systemVolume)")
            
            
            Button {
                useCustomVolume()
            } label: {
                Text("100% Volume")
            }
            
            
            Button {
                useSystemVolume()
            } label: {
                Text("System Volume")
            }
            
        }
        
        
    }
    
    func useCustomVolume() {
        systemVolume = Float(AVAudioSession.sharedInstance().outputVolume)
        MPVolumeView.setVolume(Float(1.0))
    }
    
    func useSystemVolume() {
        MPVolumeView.setVolume(systemVolume)
    }
    
}

4. Finally: You should always bear in mind that it could disturb a user in a productive version of your app, as the volume setting is usually made deliberately.

5. Usefull Documentation:

MPVolumeView (Apple Documentation)

MediaPlayer (Apple Documentation)

Upvotes: 0

Related Questions