tvOS: AVPlayer Audio Plays but there's no video - swift

I have this code as part of a tvOS app
import Foundation
import UIKit
import AVFoundation
import AVKit
class videoPlayer: UIViewController {
var thePlayer: AVPlayer?
var movieToPlay: AVPlayerItem?
let movieURL="http://trailers.apple.com/movies/independent/walkingwiththeenemy/walkingwiththeenemy-tlr1_720p.mov"
override func viewDidLoad(){
let theVideoPlayer = AVPlayerViewController()
theVideoPlayer.player = thePlayer
self.addChildViewController(theVideoPlayer)
self.view.addSubview(theVideoPlayer.view)
theVideoPlayer.view.frame = self.view.frame
let movieToPlay = AVPlayerItem(URL: NSURL(string: movieURL)!)
thePlayer = AVPlayer(playerItem: movieToPlay)
self.thePlayer!.play()
}
}
When the view is loaded the code plays audio but no video.
When one swipes the Apple TV remote a timeline appears with 0:00 duration at the right and 0:00 at the left as the audio plays. There is also a red no-smoking-like sign that appears at the left end of the timeline. My understanding is that the sign means that the video is in the wrong format, but the audio plays (and the clip is from Apple). The video plays plays in other AppleTV apps.
I think the code is correct (it works in another app) and I can't figure out next steps to debug. Can anyone see an error?

The code above worked just as expected when I placed it in a separate viewController and then presented it from the viewController where is had resided. I don't understand why, exactly, but it solved the problem video with audio issue.

Related

Black Screen when stream video with avkit

Hi I want to stream remote video on my app. URL is: http://test.ext/myvideo.mkv
I use AVKit with this code but screen and audio not works. I see only progress bar that go forward.
let player = AVPlayer(url: url)
// Create a new AVPlayerViewController and pass it a reference to the player.
let controller = AVPlayerViewController()
controller.player = player
controller.player?.automaticallyWaitsToMinimizeStalling = false
controller.player?.playImmediately(atRate: 1.0)
// Modally present the player and call the player's play() method when complete.
self.present(controller, animated: true) {
player.play()
}
AVPlayer don't support mkv video format.
Anyone have a solution for playing all video format ?
I've tested MobileVLCKit but it's too heavy (1,5Go)...

How to stream remote audio in iOS 13? (SwiftUI)

This code using AVPlayer works only on Playground
import AVFoundation
var player = AVPlayer()
let playerItem = AVPlayerItem(url: URL(string: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3")!)
player = AVPlayer(playerItem: playerItem)
player.play()
When I tried to run it on my SwiftUI App on my physical device, using this code:
Button(action:{
var player = AVPlayer()
let playerItem = AVPlayerItem(url: URL(string: "https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3")!)
player = AVPlayer(playerItem: playerItem)
player.play()
print("Works")
},label:{
Image("play")
})
It prints Works to the console. However, it does not play any sound on the device.
Would appreciate any help, can't find anything yet here.
Thank you so much!
In SwiftUI, Views are value types. They are only data that describe the things on screen. They can be created or destroyed or copied at any time. AVPlayer is a reference to a specific player object. You're assuming here that it will continue to exist, and there will only be one of them. That's not something that a SwiftUI View provides.
You need to move your AVPlayer outside of the View (into Model objects), and just bind UI actions to it.

Sound for Scene Transition, that doesn't stutter

In SpriteKit (for those unfamiliar with it) there's a way to load and unload scenes, and a transition (visual) between them.
I'm trying to make a sound play between scenes, as they transition... that doesn't stutter.
So far, all the ways I've tried either create no sound, or the sound stutters, even using a sound manager, like this:
import AVFoundation
import SpriteKit
open class SoundManager {
static let soundStart = SKAction.playSoundFileNamed("ActionBeep_AP1.7", waitForCompletion: true)
static var coinSound = NSURL(fileURLWithPath:Bundle.main.path(forResource: "ActionBeep_AP1.7", ofType: "wav")!)
static var audioPlayer = AVAudioPlayer()
open static func playCoinSound(){
guard let soundToPlay = try? AVAudioPlayer(contentsOf: coinSound as URL) else {
fatalError("Failed to initialize the audio player with asset: \(coinSound)")
}
soundToPlay.prepareToPlay()
self.audioPlayer = soundToPlay
self.audioPlayer.play()
}
}
Anyone had any success making scene transition sounds run smoothly? I realise there's a lot going on during a scene transition, and that's probably not helping the sound engine. But think there must be a way to make a clear sound play during a scene transition.
And yes, I've tried with .caf and .mp3 and .wav files, all with different "compression" and raw states. I think it's how I play the sounds that's the problem, not the file type.
As crashoverride777 said, you need to change when you load the sound manager. You could set up a thread in your didMoveToView() function to minimize loading time:
DispatchQueue.global(qos: .userInitiated).async {
// Load your sound stuff
}
Now, you have your sound file loaded for whenever you need it, lag-free.

SpriteKit overlaying audio file

I'm trying to set a background jingle for my game which is supposed to start at the Home scene and then loop continuously even while on the other scenes.
This is what my class looks like:
class AudioPlayer: AVAudioPlayer {
var audioPlayer: AVAudioPlayer? = AVAudioPlayer()
let ost = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("bkg", ofType: "mp3")!)
func playOst() {
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: ost)
}
catch {
audioPlayer = nil
}
audioPlayer?.prepareToPlay()
audioPlayer!.play()
audioPlayer!.numberOfLoops = -1
}
func stopOst() {
audioPlayer!.stop()
}
since I put the play method in the home scene, it will start playing a new track every time I load it, overlaying one track on another making it result in a big mess. How can I prevent it?
Make your audio player class a singleton, or let AppDelegate look after it. This will also allow you to control the music from any scene/screen in your app at any time.
Whenever your home screen loads check to see if music is already playing, if not, call playOst, otherwise do nothing.

How can I play an intro video the first time I launch an iPhone app using swift (NOT objective-c)?

I want to play an intro video for my iPhone app the first time it launches. I have it set up to detect that it's the first launch, but how do I play the video from the app (not a url) using SWIFT? Do I set it up in the first ViewController file or in the AppDelegate? I've tried using MPMoviePlayerController, but I just can't seem to get it to actually play. Thank you for your help!
I had this same trouble. Here's my solution:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("video", ofType:"mp4")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
player.view.frame = self.view.bounds
player.controlStyle = .None
player.prepareToPlay()
player.scalingMode = .AspectFit
self.view.addSubview(player.view)
}
}
Don't forget to import MediaPlayer and declare your variable - var moviePlayer: MPMoviePlayerController?
Then call your function when you want to play it playVideo()
See my question for how to dismiss it - In iOS how do I programmatically add a video view and then remove it after it finishes playing using Swift?
I got a really helpful answer there.
Also notice that I disabled my controllers because I don't want it to be seen.