I'm using AVKit to play a youtube URL.
I have this code inside a button action:
#IBAction func trailerButtonAction(_ sender: Any) {
guard let youtubeUrl = youtubeURL else { return }
let player = AVPlayer(url: youtubeUrl)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
present(playerViewController, animated: true) {
player.play()
}
}
The URL is valid, but when I press the button, the video doesn't stop loading and I'm getting this message on Debug area:
nw_endpoint_flow_copy_multipath_subflow_counts Called on non-Multipath connection
Edit:
I found that AVPlayer doesn't support youtube URL
I would say this log isn't necessarily relevant. I was getting this error when trying to playback on the simulator but it wasn't happening on a real device.
One workaround would be to use a 12.4.x simulator as it does not exhibit this issue. Only the 13.x simulators are showing this error. It happens to repeatedly that it slows down Simulator to a craw until all requested tracks have been buffered.
To combat this while testing, I am either not turning on AVPlayer or I am only buffering a short track.
To cut down on the number of errors try initing your AVPlayer like so:
var avPlayer : AVPlayer = AVPlayer()
This may cut down the errors by 30%.
App crashes with the following error message
2019-10-12 20:01:34.332334-0700 Awesome App[26368:3535170] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x600002903280> F8BB1C28-BAE8-11D6-9C31-00039315CD46
The breakpoint at crash seems to be related to AVAudioPlayer
let path = Bundle.main.path(forResource: "menu_background.mp3", ofType:nil)!
audioPlayer = try AwesomeAudioPlayer(contentsOf: URL(fileURLWithPath: path)) ---> breakpoint
I believe you all might have added the AVFoundation to the frameworks list in Project General Info tab.
Erroneous Code was as follows:
import SwiftUI
import AVFoundation
struct PlayerDetailView: View {
#State private var downloadedFilePath: URL = nil
var audioPlayer: AVAudioPlayer
var body: some View {
And after I moved the var audioPlayer: AVAudioPlayer declaration to just after the line of import AVFoundation line it seemed to be working.
So following code worked for me in a SwiftUI project:
import SwiftUI
import AVFoundation
var audioPlayer: AVAudioPlayer!
struct PlayerDetailView: View {
#State private var downloadedFilePath: URL = nil
var body: some View {
VStack {
Button("Play the Downloaded Track") {
if let downloadedPath = self.downloadedFilePath?.path, FileManager().fileExists(atPath: downloadedPath) {
do {
audioPlayer = try AVAudioPlayer(contentsOf: self.downloadedFilePath!)
guard let player = audioPlayer else { return }
player.prepareToPlay()
player.play()
} catch let error {
print(error.localizedDescription)
}
} else {
print("The file doesn not exist at path || may not have been downloaded yet")
}
}
}
}
}
I was initially following this tutorial of CodeWithChris and its discussion also led to above change. Also checkout following tutorial too if you need further examples.
Hope this will be helpful to someone of you out there!
Cheers!
I believe the error message is a warning for simulators hence it is not important.
I think your issue is a bug in your code. Should be something like this:
let path = Bundle.main.path(forResource: "menu_background", ofType:"mp3")
audioPlayer = try AwesomeAudioPlayer(contentsOf: URL(fileURLWithPath: path!)) ---> breakpoint
Where the forResource is the name of the file and ofType is the extension.
You can also use Bundle.main.url which will look like this:
let path = Bundle.main.url(forResource: "menu_background", withExtension:"mp3")
audioPlayer = try AwesomeAudioPlayer(contentsOf: URL(fileURLWithPath: path!)) ---> breakpoint
I think it has to do with the AVAudioPlayer going out of scope before the simulator device is able to queue up the sound and play it...or something along those lines. I'm brand new to Swift and I have zero experience with iOS APIs.
Here's what I discovered after experimenting with the placement of:
var player: AVAudioPlayer!
The sound will either PLAY or NOT PLAY depending on the placement of the line above.
Regardless, the following error will always occur on my Simulator devices:
AddInstanceForFactory: No factory registered for id
(I'm on a Late 2013 MacBook Pro + MacOS Catalina + Xcode 11.7 and I tested this on an iPhone SE 2 simulator running iOS 13.7)
Although the error keeps occurring, I'm happy that I at least got the sound to play on the Simulator...
Error occurs and sound DOES NOT play...
import UIKit
import AVFoundation
class ViewController: UIViewController {
func playTheSound() {
// initializing the "player" variable within the "playTheSound()" function will cause the "AddInstanceForFactory: No factory registered for id" error and the sound WILL NOT play on the simulator
var player: AVAudioPlayer!
let url = Bundle.main.url(forResource: "funny_sound", withExtension: "mp3")
player = try! AVAudioPlayer(contentsOf: url!)
player.play()
}
}
Error occurs and sound DOES play
import UIKit
import AVFoundation
class ViewController: UIViewController {
// initializing the "player" variable at the class level will still cause the "AddInstanceForFactory: No factory registered for id" error to happen, but the sound will still play on the simulator
var player: AVAudioPlayer!
func playTheSound() {
let url = Bundle.main.url(forResource: "funny_sound", withExtension: "mp3")
player = try! AVAudioPlayer(contentsOf: url!)
player.play()
}
}
In my case totally different...
The issue is solved after doing...
var player = AVAudioPlayer()
It didn't work in...
var player:AVAudioPlayer!
(Xcode 12.2)
I think I have solved the issue (hard to prove a negative, since the error was sporadic). I have my AVAudioPlayer in a separate class:
import SwiftUI
import AVFoundation
var audioPlayer: AVAudioPlayer?
class AudioManager {
var userSettings = UserSettings()
func playSoundEffect(_ assetName:String) {
if !userSettings.soundDisabled {
guard let audioData = NSDataAsset(name: assetName)?.data else {
fatalError("Unable to find asset \(assetName)")
}
do {
audioPlayer = try AVAudioPlayer(data: audioData)
audioPlayer?.prepareToPlay()
audioPlayer?.play()
} catch {
print(error.localizedDescription)
}
}
// audioPlayer?.stop()
}
func stopPlay() {
audioPlayer?.setVolume(0.0, fadeDuration: 0.25)
}
}
Then, in the SwiftUI views where I need to play audio, be certain to import AVFoundation.
import SwiftUI
import AVFoundation
struct MyView: View {
...
let audioManager = AudioManager()
...
}
I have found the solution in another stackoverflow thread about AVAudioPlayer, here it is :
If you initialize your AVAudioPlayer like
var wrongMusicPlayer: AVAudioPlayer = AVAudioPlayer() OR wrongMusicPlayer = AVAudioPlayer() in any method then please remove it and just Declare like var wrongMusicPlayer: AVAudioPlayer!.
You could use do/catch to avoid the crash and examine the exception, or ignore the issue all together with try?. For me, this was only showing up in the simulator when calling:
try? AVAudioSession.sharedInstance().setCategory(.playback)
I think it's safe to ignore it in my case.
Similar problem - using Preferences > Sound > Output different than Logictech USB Headset led to app that executed perfect & played sound w/o problems. Was never a problem outside of the Simulator - code on a device worked fine.
TL;DR
This is an especially gnarly & obtuse problem. I also encountered an issue with an unexpected:
No factory registered for id
After a short wait, it was also followed by several other console-reported errors, including:
HALC_ProxyIOContext::IOWorkLoop: the server failed to start, Error:
AQMEIO.cpp:182:AwaitIOCycle: timed out after 15.000s
CA_UISoundClient.cpp:244:StartPlaying_block_invoke: CA_UISoundClientBase::StartPlaying: AddRunningClient failed
error when trying to play sound. Xcode 12.2, Mac OSX Catalina 10.15.7, simulator running iOS 14.2.
Code had previously worked on prior versions of the simulator.
Always had proper import of AVFoundation & declaration of AVAudioPlayer class property as:
var audioPlayer: AVAudioPlayer!
In my case it seems to be related to audio drivers in Mac OSX. This problem ONLY happened when I had Mac System Preferences > Sound > Output set to my Logitech USB Headset. The code otherwise worked when: played through my LG Monitor, played through my AirPods Pro, and when executing outside the simulator and on a device > my iPhone 11 Pro.
Spent over an hour trying to diagnose the issue before restarting & noticing audio working when headset wasn't used for output. Switching the Preferences > Sound > Output settings to something other than the Logitech USB headset immediately fixed the problem in all other playback instances.
Not even sure where to file this issue as an Apple bug, but hoping it helps someone. Am assuming it's an OS-specific issue & not one that'll result in a problem w/the app or code.
I found a solution in Here2Huynh's answer.
let path = Bundle.main.path(forResource: "menu_background.mp3", ofType:nil)!
here change
ofType:nil
to
ofType: "mp3"
and then again.There is no error message when using the emulator.
By the way, I am using the swiftui project
Simulator -> I/O -> Keyboard -> uncheck all
I am trying to playback youtube videos with tvml on my appleTV. It is based on:
https://gist.github.com/nickv2002/b7bb28cdccc000bdb910
The first time I start it, it is working, but after I play around (leaving the app), I get:
ReferenceError: Can't find variable: playYTblock
After rebooting/exit(0)ing the app the ATV it is working again... it seems, the context between the app<>tvjs is lost - anyone with ideas?
Here is my code:
in AppDelegate.swift
let playerVC = YTPlayerViewController()
in the application function:
playerVC.createPlayYT( appController! )
in presenter.js
if (youtubeUrl && (event.type === "play")) {
playYTblock(youtubeUrl);
}
in the template.xml.js
<listItemLockup youtubeUrl="H4O6oEaIDrs">
btw has anyone an idea why the event.type === select is fired right after loading the template (without clicking on my side)
Can't answer about that exact problem but,
Here is what i'm using is to play youtube video on tvos :
pod "AKYoutubeParser"
A parser to retrieve the actual youtube video urls.
And the video playback is handled by apple core stuff (AVFoundation, AVKit)
you can delete all the hud part if you don't use it.
import AKYoutubeParser
import AVFoundation
import AVKit
func displayTrailer(trailer: String) {
AKYoutubeParser.h264Streams(trailer) { [weak self] streams, error in
if let s = streams, v = AKYoutubeParser.getBestQuality(s) {
let playerVC = AVPlayerViewController()
let playerItem = AVPlayerItem(asset: AVAsset(URL: v.url))
let videoPlayer = AVPlayer(playerItem: playerItem)
playerVC.player = videoPlayer
self?.presentViewController(playerVC, animated: true) {
playerVC.player?.play()
}
}
}
}
I'm trying to find a way with AVFoundation to play audio when the user is on the lock screen or if they lock the app in the middle of using my app
class ViewController: UIViewController, AVAudioPlayerDelegate {
var avPlayer: AVAudioPlayer?
var error: NSError?
... other stuff ...
func playChime(fileName: String) -> Void {
let fileURL: NSURL! = NSBundle.mainBundle().URLForResource(fileName, withExtension: "wav")
self.avPlayer = AVAudioPlayer(contentsOfURL: fileURL, error: nil)
self.avPlayer?.play()
}
... other stuff ...
}
What needs to be added to this to ensure sounds play when the user is on the lock screen as well?
To continue playing audio in the background when the device is locked or on the home screen (on Xcode 6.3):
Add to your ViewController:
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
Then in your Info.plist, add a new entry for UIBackgroundModes and set it to audio. Xcode will automatically fill it out as 'Require background modes' and 'App plays audio or streams audio/video using Airplay'
I am updating an existing app to Swift. The issue I am having is that the main purpose of the app is to play a sound file when the app gets to a specific location. Everything works in the simulator, but it does not play the sound on the device. If I add the background mode for audio and airplay, it works flawlessly. Apple has rejected this as it doesn't use the audio all the time, just when it enters a region. I did not have to have audio and airplay background mode enabled for iOS7.
I think it has something to do with the audioplayer being dealocated before it has a chance to be used. I cannot figure out how to get it set properly. There is this same question on StackOverflow for Objective C, but I cannot find anything similar for swift (and to me, this is what the answer to that question suggests and the way I had it set for iOS7).
class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate, CLLocationManagerDelegate, AVSpeechSynthesizerDelegate, AVAudioPlayerDelegate {
var myManager: CLLocationManager!
var audioPlayer = AVAudioPlayer()
var mySpeechSynthesizer = AVSpeechSynthesizer()
func playSound()
{
audioPlayer.prepareToPlay()
audioPlayer.play()
}
func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool)
{
speak()
}
func speak()
{
var myString = "This is the phrase I want to speak"
var mySpeechUtterance:AVSpeechUtterance = AVSpeechUtterance(string:myString)
mySpeechUtterance.rate = 0.12
mySpeechUtterance.voice = AVSpeechSynthesisVoice(language: "en-US")
mySpeechSynthesizer .speakUtterance(mySpeechUtterance)
}
func locationManager(manager: CLLocationManager!, didEnterRegion region: CLRegion!)
{
playSound()
scheduleAllLocations()
}
override func viewDidLoad()
{
super.viewDidLoad()
myManager = CLLocationManager()
myManager.delegate = self
myManager.desiredAccuracy = kCLLocationAccuracyBest
myManager.requestAlwaysAuthorization()
var alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("SpeakMinder", ofType: "mp3")!)
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
audioPlayer.delegate = self
mySpeechSynthesizer.delegate = self
}
This is the complete code. It works flawlessly if I have audio/airplay enabled in the background. Doesn't play a sound or speak if I have the audio/airplay disabled in the background. (Apple has rejected the app for having audio/airplay enabled)
From the Technical Team
If you are attempting to use AVSpeechSynthesizer from the background you should have the background audio key enabled. AVSpeech simply uses the same audio plumbing as playing any sound.
Regarding it working in iOS7 without having audio in the background enabled
If this key was not required, you were most likely getting lucky due to a bug that we have since corrected.
And an app was approved today with the audio background enabled.
If you are rejected due to having audio enabled in the background for the Speech Synthesizer.
Our own Location Based sample “Breadcrumbs" has the following enabled in the plist. You may point to this sample in your appeal.