I'm building an app where the user can shoot a video.
We've noticed that after presenting the camera and dismissing it, the mute switch is no longer respected and the sound from the video is audible! The video is played with an AVPlayer.
Is this a bug for Apple?
It is not a bug. AVPlayer lets you categorize your audio playback to tell iOS your intent. Here's how to set it:
[[AVAudioSession sharedInstance] setCategory:cat error:&err];
where cat is one of
AVAudioSessionCategoryAmbient: String
AVAudioSessionCategorySoloAmbient: String
AVAudioSessionCategoryPlayback: String
AVAudioSessionCategoryRecord: String
AVAudioSessionCategoryPlayAndRecord: String
AVAudioSessionCategoryAudioProcessing: String
AVAudioSessionCategoryMultiRoute: String
For example, the documentation for AVAudioSessionCategoryPlayback says
When using this category, your app audio continues with the Silent switch set to silent or when the screen locks.
Setting it to AVAudioSessionCategorySoloAmbient should make it respect the Mute button.
Related
How to keep the video player silent after the video recorder has been initialized and the silent switched is turned on?
In the application I am working on I have a video player (will call it player) and a video recorder (will call it recorder). If the phone is in silent mode (the switch on the side of the device is turned on to disable the sound) the player is kept silent when entering the application which is an expected and desired result. But after the recorder has begun running the session this behavior is lost and the video will play out loud although the silent mode is enabled.
I know specifically where this happens is when startRunning is called on an AVCaptureSession.
I also know the reason is somewhere in [AVAudioSession sharedInstance] category or mode property which seem to be changed right after the session begins running.
So what I do at the moment is call
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:&error];
[[AVAudioSession sharedInstance] setMode:AVAudioSessionModeDefault error:&error];
after the recording is completed to reset the session. The issue is this works in most but not all cases, sometimes reports error, sometimes works with a delay, sometimes doesn't work at all.
The possible solutions I am looking for are (any would do):
Somehow prevent the recorder to enable sound playing
Have a clear way of resetting the category and mode after the recording has completed (no errors or misbehaving)
Have a clean solution to find the state of the silence button (seems the old functions are deprecated and I found nothing but hacks)
Any other ideas welcome
An important information is that I have both the player and a recorder initialized all the time for a quick usage. Also I can control the player to be mute.
What I use for player:
AVFoundation
AVPlayer
AVPlayerLayer
The source is an AVAsset representing a remote URL
The implementation is pretty standard.
What I use for the recorder:
AVFoundation
AVCaptureDeviceInput
AVCaptureMovieFileOutput
AVCaptureVideoPreviewLayer
Again all pretty standard.
Im using YouTube Helper Library to play YouTube videos on my iOS application
Here are link of Library
I just need a way to continue audio (or video) playing in background ,
So when user click on home button i need him to be able to hear the voice
of the video ,
even when he lock his device i need to him to be able to control the sound and
click next and back button for audio playing ..
How i can achieve that on YouTube Helper Library ?
NOTE: many application do that and they exist on app-store like iMusic , Video Tube ,MusicTV , MB2
Playing background video (or voice) is against the YouTube TOS. You can not do it with this library for sure, even if you figure out a workaround, your app would be taken down because of TOS violation.
About playing sounds in background:
You have to set the AVAudioSession category to AVAudioSessionCategoryPlayback and add the audio value to the UIBackgroundModes key in your information property list file.
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &setCategoryError];
I have tested this code on iOS 7 and up only, so it may not work for earlier versions.
From Apple docs:
AVAudioSessionCategoryPlayback The category for playing recorded music
or other sounds that are central to the successful use of your app.
When using this category, your app audio continues with the Silent
switch set to silent or when the screen locks. (The switch is called
the Ring/Silent switch on iPhone.) To continue playing audio when your
app transitions to the background (for example, when the screen
locks), add the audio value to the UIBackgroundModes key in your
information property list file.
see references here and here
You need to enable it when app enter background. Remember to check your app is in background
func playerView(_ playerView: YTPlayerView, didChangeTo state: YTPlayerState) {
if state == .paused {
playerView.playVideo()
}
}
Is it possible to play audio with AVAudioPlayer in the background and also mute it with the mute switch on iPhone?
I know I can play audio in the background if I set AVAudioSessionCategoryPlayback but it will not mute with the mute switch. Or if I set AVAudioSessionCategoryAmbient - it will be muted by a switch but also when pressing home button for example - and I don't want that to happen.
UPDATE:
I have "App plays audio or streams audio.." in "Required background modes" - so when i set AVAudioSessionCategoryPlayback it continues playing in background even after pressing home button but the mute switch has no effect.
No, the desired behaviour is not possible with the available AVAudioSession categories. This might be on purpose to avoid unwanted battery loss or data costs for the users. Users can still decide to lower the volume to zero with the volume buttons of course.
Since there is also no public API anymore to detect the status of the silent/mute switch anymore, workarounds/hacks are tricky and might be declined on App Store submission.
I have done several apps with buzztouch for Iphone and Ipads, here is a free one as an example :
http://itunes.apple.com/us/app/lr-basics-free-edition/id497563707?mt=8
I do not know code very much, I have very little basics that is why I designed my app using Buzztouch, which by the way is amazing !
The only one problem that I have is that the default behavior when you play a video (which was most of my apps are doing, playing tutorials) and if the silent mode is on either on Ipad or Iphone, there is no audio, even thought the volume slider is active, given the impressions to users that there is a bug, and I got some bad reviews due to that, I have also people writing me about it. I Then tell them all they have to do is to turn off the silent mode and they the audio is back, works everytime, but in the meantime I get complaits !
So here is my questions, is there a simple way I can located in the Buzztouch generated code a property that can easely be changed so that when a video is played, audio stays, despiste the silent mode being active.
I actually checked 4 or 5 other Iphones similar applications including the default youtube apple app, the default is that the audio plays even if the silent mode is turn on, giving my customer the impression that my app is bugged.
I'm not a programmer so please but as simple as possible in your answer.
Tku so much for the help.
Serge
What you are describing is the default behavior in iOS - when the ring/silent switch is in silent mode all audio from your app will be suppressed.
I don't know about implementing this from BuzzTouch, but here is a native solution I used to get around this for one of my apps that plays video:
MPMoviePlayerViewController *mpvc = [[MPMoviePlayerViewController alloc] initWithContentURL:myVidURL];
... set up player ...
// prevent mute switch from switching off audio from movie player
NSError *_error = nil;
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: &_error];
[self presentMoviePlayerViewControllerAnimated:mpvc];
You will also need to include the AVFoundation framework for this to work.
Here's the link where I first found this tip:
http://www.24100.net/2011/05/ignore-ringtone-mute-switch-during-mpmovieplayer-video-playback-ios/
Right from documentation - iOS has 6 audio session categories out of that 3 affects the behavior of Slient switch:
AVAudioSessionCategoryAmbient or the equivalent kAudioSessionCategory_AmbientSound— Using this category, your audio is silenced by the Ring/Silent switch and when the screen locks. Used when we want our app audio with built-in app audio
AVAudioSessionCategorySoloAmbient or the equivalent kAudioSessionCategory_SoloAmbientSound—Use this category for an application whose audio you want silenced when the user switches the Ring/Silent switch to the “silent” position and when the screen locks. This is the default category
AVAudioSessionCategoryPlayback or the equivalent kAudioSessionCategory_MediaPlayback—Use this category for an application whose audio playback is of primary importance. Your audio plays even with the screen locked and with the Ring/Silent switch set to silent.
Hint: Upload the audio file to your buzztouch account files. This is the only way Buzztouch will recognize the audio. next, add the audio file to your xcode bttouch sound folder and add all references. You should be fine!
I need to play a custom sound synthesized using AudioUnit on an iPod.
This sound shall be played after up to one hour of playing music from a playlist on the iPod (it is played using MPMusicPlayerController).
The issue is that everything works fine if the screen in on, however my custom sound doesn't play if the screen is off.
If the sound is already playing when the screen is turned off it keeps playing well. So I assume I am using the correct audio session category.
Could you give me any hint?
According to Apple's developer library:
AVAudioSessionCategoryPlayback or the equivalent
kAudioSessionCategory_MediaPlayback—Use this category for an
application whose audio playback is of primary importance. Your audio
plays even with the screen locked and with the Ring/Silent switch set
to silent.
(Also, check this table.)
It seems that setting the audio session category to AVAudioSessionCategoryPlayback or kAudioSessionCategory_MediaPlayback would automatically fix your problem.