MPMusicPlayer Error Domain=MPErrorDomain Code=4? - ios

I am having issue with Music player, most of the songs gives Error
Error Domain=MPErrorDomain Code=4
The testing device has Apple music subscription and the tracks gives error on the app they are working fine in Apple music app!
Here is the code:
let applicationMusicPlayer = MPMusicPlayerController.systemMusicPlayer()
applicationMusicPlayer.setQueueWithStoreIDs([ID])
if #available(iOS 10.1, *)
{
applicationMusicPlayer.prepareToPlay { (error) in
if (error != nil)
{
print("[MUSIC PLAYER] Error preparing : \(String(describing: error))")
return
}else
{
self.start_timer();
self.applicationMusicPlayer.play()
}
}
}else
//Play directly ios below version 10.1
{
self.applicationMusicPlayer.play()
}
}
But what I've tried, when the track gives this error, I went to Apple music player and played it from there its worked, then I came back to my app and play it from my app its worked also fine, so I need to go to Apple music app to play tracks not playing in my app to make them work in my app! That's so weird any idea why?
PS: the testing device has Apple music subscription

I had some similar problems when adding songs to a playlist, solved it by using:
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) {
// Code
}
i would play around with waiting a bit before or after preparing.
5 seconds may be too much, but you can start from there

Related

How can I detect if my audio streaming url can not be play by iOS device - swift3

I am making an iOS Radio app with Swift 3! Now it is working and playing all the url address audio streaming well. But when I am in my workplace the Wifi has restrictions for Play audios streaming, so the app just works with Mobile Data.
When I click on Play button it change to Pause and does not send any sounds, It does not play and the console does not show any connectivity error or something like that. I want to know when the firewall or proxy of some WIFI network is blocking my app to send some UIAlert and change the Pause icon to Play ( if i do not do it the user will be waiting for the music).
I am using Swift 3.0 Xcode 8 , AVPlayer to play the audio. I have tried .addPeriodicTimerObserver, I have validated the url and did a lot of things but I could not get the result that I am looking for. Can some one help me?
var urlStreaming:String = "http://someurl"
playerStreaming = AVPlayer(url: URL(string: url)!)
playerLayer = AVPlayerLayer(player: playerStreaming)
playerLayer.frame = CGRect(x:0, y: 0, width:1, height: 10)
self.view.layer.addsublayer(playerLayer)
playerStreaming?.play()
My playerStreaming?.play() is not sending me nothing when It can not play because it starts trying to play but after some seconds it stops and it does not send anything. When I using WIFI connection of my workplace it happens, but If i change it to mobile data I can listening the audio. If i play from another wifi connection for example my house, park or starbuck coffee wifi I can listening it too without problems.
I know that the Wifi connection in my workplace has restriction (blocked by firewall or proxy actually I am not sure. )for audio streaming.
I have been looking for a lot of options and I tried all of them but i had gotten the result that I am looking for.
Can you help me?
I think i found something to check it. What do you thing #zombie?
I checked if the url is valid or how much it takes to play.
P.S. Maybe I will change the Time Out value , now it is taking to much time.
Console shows:
Error Info: -> Error Domain=NSURLErrorDomain Code= -1001 "the request time out" . i think I can validate if my error is null or not. if it is null I can show a UIAlert
let urltest = URL(string: yourul)
let task = URlSession.shared.dataTask(with: urlTest!){
data, response, error in
if(error != nil){
print("Error info: -> \(error!)")
//I think here I can changes the Image if i found a error
}
else{
print("It is going to be play without problem")
}
}
You can listen for error by
NotificationCenter.default.addObserver(self, selector: #selector(playerItemFailedToPlay(_:)), name: NSNotification.Name.AVPlayerItemFailedToPlayToEndTime, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(playerItemFailedToPlay(_:)), name: NSNotification.Name.AVPlayerItemPlaybackStalled, object: nil)
func playerItemFailedToPlay(_ notification: Notification) {
let error = notification.userInfo?.first(where: { $0.value is Error }) as? Error
}
don't for get to remove the observer
deinit {
NotificationCenter.default.removeObserver(self)
}

replaykit startrecording sometimes never enters completion handler

I am using replay kit to save a video of my screen during gameplay but randomly on occasion startRecordingWithMicrophoneEnabled and recorder.stopRecordingWithHandler never enters the completion handler
it doesn't throw an error, it just runs and hangs indefinitely.
if recorder.available && recorder.microphoneEnabled {
recorder.startRecordingWithMicrophoneEnabled(true) { [unowned self] (error) in
if let unwrappedError = error {
print(unwrappedError.localizedDescription)
} else {
print("called")
self.manager.instructions.text = "Click to Start Game"
}
}
}
if recorder.available && recorder.microphoneEnabled {
print("initiating stop recording")
recorder.stopRecordingWithHandler { [unowned self] (RPPreviewViewController, error) in
print("in completion handler")
if let previewView = RPPreviewViewController {
print("will transition to gameplay video")
previewView.previewControllerDelegate = self
self.presentViewController(previewView, animated: true, completion: nil)
self.sessionHandler.session.stopRunning()
}
}
}
I was getting this same thing. Was working on one device, and not on another. Only difference was the working device was on iOS version 10.1.0 and the other was iOS version 10.0.2 - upgraded to 10.2.0 and it started working immediately.
I had the same problem and just found its cause (or maybe just a cause). If your device is connected to a WiFi that has no internet access this problem occurs. If you connect it to a WiFi that has internet access or disable WiFi it works just fine. I guess when starting a recording, ReplayKit tries to connect to some Apple servers but never reaches them and also never times out. You can observe the same behavior with the App Store. When you are connected to a WiFi without internet it tries to load the store forever and never times out.

ReplayKit sharing video to facebook has no commentary

I'm recording a video with commentary, and I'm using replaykit. Everything is working fine on iPhone, but when I share to facebook, my videos has no sound at all. I've downloaded a video to my mac and it's m4v with sound. But when I'm trying to share it from my mac to facebook it doesn't has sound too. On youtube it works very good. Not sure is there any way I can fix it? Can I record a screen and commentary without replaykit and pass app review?
Start:
RPScreenRecorder.shared().isMicrophoneEnabled = true
RPScreenRecorder.shared().startRecording { (error) in
if error == nil {
//TODO: show RECORDING view
print("start recording")
}
}
Stop:
RPScreenRecorder.shared().stopRecording { (previewViewController, error) in
if let previewVC = previewViewController, error == nil {
previewVC.previewControllerDelegate = self
self.present(previewVC, animated: true, completion: nil)
}
}
Seems to be Fixed by Apple
(on the latest IOS 11 Beta's update)
Ofir Malachi I will write it as an answer, I used some parts of Spitfire library, I'm doing a screenshot of this part of the screen I want to "record" every 0.1 second. I'm merging those images to a video. In the same time I'm recording audio. At the end I've got "output.mov" and "recording.m4a". I'm using AVAssetExportSession to merge it asynchronously to the mp4 file.

AVAudioSession: Some Bluetooth devices are not working properly on my App

I'm developing a swift audio/video and text chat iOS App using AVAudioSession.
Whenever I select to use some Bluetooth devices the sound played on the device is not the App audio stream. They play only the system sound sent by text chat library whenever messages are sent/received instead. It doesn't happen on all Bluetooth devices, on some of them everything works fine. On Builtin Mic and Speaker the App works fine too.
Here are the most important methods from my class to manage the device:
class MyAudioSession
{
private var mAudioSession: AVAudioSession;
init!()
{
self.mAudioSession = AVAudioSession.sharedInstance();
do {
try self.mAudioSession.setActive(false);
try self.mAudioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: .AllowBluetooth);
try self.mAudioSession.setMode(AVAudioSessionModeVideoChat);
try self.mAudioSession.setActive(true);
}
catch {
return nil;
}
}
func switchToDevice(device: AVAudioSessionPortDescription!) -> Bool
{
var ret = false;
if (device != nil) {
do {
try self.mAudioSession.setPreferredInput(device);
ret = true;
}
catch {
self.logSwitch(device, error: error);
}
}
return ret;
}
}
I'd like to understand why my App is not working fine on just SOME Bluetooth devices. These same devices work properly on the other Apps on my Cel.
I did another test: I changed all of this for MPVolumeView, and exactly the same issue occurred, so the problem seems to be on audio player.
Could anybody give me a suggestion to fix this ?
Thx.
Jorg,
While this might not be the best answer I have been able to overcome the weird Bluetooth issues. My problem seems to be similar to yours as I too was using:
AVAudioSessionCategoryPlayAndRecord
This was causing issues for me on some Bluetooth devices (not all but some).
What I wound up doing was setting the Category to:
AVAudioSessionCategoryPlayback
Then when ever I needed to record I would switch the Category over to:
AVAudioSessionCategoryRecord
Then back to Playback after completing my recording.
This was the only way at this time I could get a consistent result from switching between the different outputs (Speaker, Headphones, Bluetooth).
Hope that helps some. Guessing this is a bug in the "AVAudioSessionCategoryPlayAndRecord"

Using Spotify/background music with camera open

I have an app that needs to have:
Background music playing while using the app (eg. spotify)
Background music playing while watching movie from AVPlayer
Stop the music when recording a video
Like Snapchat, the camera-viewcontroller is part of a "swipeview" and therefore always on.
However, when opening and closing the app, the music makes a short "crack" noise/sound that ruins the music.
I recorded it here:
https://soundcloud.com/morten-stulen/hacky-sound-ios
(3 occurrences)
I use these settings for changing the AVAudiosession in the appdelegate didFinishLaunchingWithOptions:
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord,withOptions:
[AVAudioSessionCategoryOptions.MixWithOthers,
AVAudioSessionCategoryOptions.DefaultToSpeaker])
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("error")
}
I use the LLSimpleCamera control for video recording and I've set the session there to:
_session.automaticallyConfiguresApplicationAudioSession = NO;
It seems others have the same problem with other camera libraries as well:
https://github.com/rFlex/SCRecorder/issues/127
https://github.com/rFlex/SCRecorder/issues/224
This guy removed the audioDeviceInput, but I kinda need that for recording video.
https://github.com/omergul123/LLSimpleCamera/issues/48
I also tried with Apple's code "AvCam", and I still have the same issue. How does Snapchat do this?!
Any help would be greatly appreciated, and I'll gladly provide more info or code!
I do something similar to what you're wanting, but without the camera aspect, but I think this will do what you want. My app allows background audio that will mix with non-fullscreen video/audio. When the user plays an audio file or a full screen video file, I stop the background audio completely.
The reason I do SoloAmbient then Playback is because I allow my audio to be played in the background when the device is locked. Going SoloAmbient will stop all background music playing and then switching to Playback lets my audio play in the app as well as in the background.
This is why you see a call to a method that sets the lock screen information in the Unload method. In this case, it is nulling it out so that there is no lock screen info.
In AppDelegate.swift
//MARK: Audio Session Mixing
func allowBackgroundAudio()
{
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, withOptions: .MixWithOthers)
} catch {
NSLog("AVAudioSession SetCategory - Playback:MixWithOthers failed")
}
}
func preventBackgroundAudio()
{
do {
//Ask for Solo Ambient to prevent any background audio playing, then change to normal Playback so we can play while locked
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
} catch {
NSLog("AVAudioSession SetCategory - SoloAmbient failed")
}
}
When I want to stop background audio, for example when playing an audio track that should be alone, I do the following:
In MyAudioPlayer.swift
func playUrl(url: NSURL?, backgroundImageUrl: NSURL?, title: String, subtitle: String)
{
ForgeHelper.appDelegate().preventBackgroundAudio()
if _mediaPlayer == nil {
self._mediaPlayer = MediaPlayer()
_mediaPlayer!.delegate = self
}
//... Code removed for brevity
}
And when I'm done with my media playing, I do this:
private func unloadMediaPlayer()
{
if _mediaPlayer != nil {
_mediaPlayer!.unload()
self._mediaPlayer = nil
}
_controlView.updateForProgress(0, duration: 0, animate: false)
ForgeHelper.appDelegate().allowBackgroundAudio()
setLockScreenInfo()
}
Hope this helps you out!

Resources