nstudio / nativescript-audio

:microphone: NativeScript plugin to record and play audio :musical_note:
Other
150 stars 104 forks source link

volume not working as expected - ios #106

Open karthiksbhat opened 6 years ago

karthiksbhat commented 6 years ago

I'm trying to check if the volume is non-zero (not on mute, basically) and alert the user to increase the volume on a screen.

My code is just:

var player = new audio.TNSPlayer(); // init
...
(somewhere else in the code)
if (player.volume == 0) {
        dialogsModule.alert({
            message: "Please increase your device's volume",
            okButtonText: "OK"
        });
        return;
    }

This works as expected on Android - if muted, alert pops up. Skips if not. (Note: on a Samsung Android device v7.0, the volume range is 0 to 15, not 0 to 1)

It works very weirdly on iOS (Xcode simulators: iOS 11.3): Before any audio has been played, the player.volume is always 0. (irrespective of current volume level on the simulator or the Mac running the simulator) After some audio has been played once, the player.volume is always 1. (irrespective of any change after that). [this is therefore causing my code to get stuck forever without playing any audio because it's always 0]

Am I using it wrong?

tns-ios : 4.0.1
tns-android : 4.0.1
tns-core-modules : ^3.4.0
nativescript-audio : ^4.0.3
bradrice commented 6 years ago

I too am having issues changing the volume. If I console.log the volume it prints out 13 regardless of what I do.

bradmartin commented 6 years ago

Not able to reproduce the iOS player returning 13. volume on AVAudioPlayer is 0.0 = 1.0 (https://developer.apple.com/documentation/avfoundation/avaudioplayer/1389330-volume) I just ran the demo app, added an interval to log out the volume of the AVAudioPlayer every 2 seconds, started dragging the volume slider in the demo app and got the following output:

CONSOLE LOG file:///app/tns_modules/nativescript-audio/common.js:18:20: NativeScript-Audio - TNSPlayer audio track duration,202.24
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 1
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 1
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.7484143972396851
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.3319239020347595
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.3319239020347595
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.08668076246976852
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.31289640069007874
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.486257940530777
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.6321353316307068
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.6321353316307068
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.6321353316307068
CONSOLE LOG file:///app/main-view-model.js:346:28: volume tracking 0.6321353316307068

The volume setting in the demo app also worked as expected. Could you try running the demo app to see if you can reproduce the issue and if so, send me the project over so I can look at what you are experiencing. Thanks.

The demo app uses the following to set audio

  // Set player volume
    if (this._slider) {
      this._slider.on('valueChange', (data: any) => {
        this._player.volume = this._slider.value / 100;
      });
    }
bradmartin commented 6 years ago

@karthiksbhat - from your version print above, you're running 4x runtimes with 3x core modules. Not saying that's your issue but you can update core-modules to 4x if you have 4x runtimes and shouldn't experience any issue.

Hopefully the demo app helps, provide any more input if you can. šŸ‘

bradrice commented 6 years ago

My issue was android not ios. Android is not setting volume. Ios is working correctly.

bradmartin commented 6 years ago

Ah you didn't mention that in your comment and the issue is titled for iOS. I'll look at Android but believe it worked fine last I ran the demo. Could be some Android API/device specific issue since manufacturers sometimes do weird crap to the way they handle stuff like audio and video

bradmartin commented 6 years ago

@bradrice - I just peeked the android source code

 get volume(): number {
    // TODO: find better way to get individual player volume
    const ctx = this._getAndroidContext();
    const mgr = ctx.getSystemService(android.content.Context.AUDIO_SERVICE);
    return mgr.getStreamVolume(android.media.AudioManager.STREAM_MUSIC);
  }

and it's currently using the device volume, I don't remember how/why this happened in the plugin, I think there were some challenges getting the mediaplayer volume stream when the plugin was written but it's been years. At any rate, change the volume on the device/emulator and you should see the value change from 13.

karthiksbhat commented 6 years ago

@bradmartin I tried with the upgraded tns-core-modules (^4.x) and the same issue persists. I tried to get the demo running (tns run android from within the demo folder) and it threw an error saying Failed to find module: "nativescript-audio", relative to: app/tns_modules/. I'm guessing I'm missing some very basic step in the process... šŸ˜…

To clarify though, I'm not trying to ever set the volume; just get it and alert the user to increase the volume if the device is muted. i.e. I expect the volume to say 0 when I've muted the device, and say something higher when I use the phone's physical volume buttons to increase the volume.

Further, another thing I noted--in my app--about this plugin and iPhones was that: The plugin (by default at least AND when on speakerphone--no headphones connected) uses the device's "ringer" volume (the bell icon) while attempting to play sound rather than the "media" volume (the speaker/volume icon). This goes against the convention. So if the phone is on mute (the physical button pushed down), audio is played, but never heard, irrespective of the "media" volume. If the phone is removed off mute, the audio is heard.

Is this normal behavior? I could create another issue for this if you're able to reproduce it too.

EddyVerbruggen commented 6 years ago

Sharing my experience (and solutions) since I ran into something similar.

Reading the volume on iOS

The plugin always gives me 1, no matter the volume setting, but this will give me the accurate setting (from 0 to 1):

const vol = AVAudioSession.sharedInstance().outputVolume;

Ignoring the hardware mute button on iOS

As mentioned by @karthiksbhat the plugin doesn't play back audio when the hardware mute button is enabled. Doing this will allow playback in that case:

AVAudioSession.sharedInstance().setCategoryError(AVAudioSessionCategoryPlayback);