How do i stream a mp3 file with swift in an app? - ios

I have an MP3 file, and I want to be able to play this file with 'Media Player' Framework. How do I upload this file onto a URL? I tried putting it on YouTube, then putting the YouTube URL in the app, but it does not work. What do I do?
Here is my code for the app:
import UIKit
import MediaPlayer
class AudioViewController: UIViewController {
var movie:MPMoviePlayerViewController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
self.playAudio("https://www.youtube.com/embed/tQsxOtH8-RQ")
}
func playAudio(URL:String){
let movieurl:NSURL? = NSURL(string: "\(URL)")
if movieurl != nil {
self.movie = MPMoviePlayerViewController(contentURL: movieurl!)
}
if self.movie != nil {
self.presentViewController(self.movie!, animated: true, completion: nil)
self.movie?.moviePlayer.play()
}
}
}

Your code is fine. The code snippet below also works. The current problem you are experiencing is due to trying to play a youtube/vimeo stream in the MPMoviewPlayerViewController. If you want to stream from those sites, you will have to use a UIWebView. There are some custom players on GitHub and elsewhere, but if you will use the snippet below and replace the URL with an mp3 hosted on your own site (i.e. WordPress) somewhere, it will play just fine.
var url = NSURL(string: "non-youtube/vimeo URL")
var mediaPlayerController = MPMoviePlayerViewController(contentURL: url)
self.presentViewController(mediaPlayerController, animated: true, completion: nil)
mediaPlayerController.moviePlayer.prepareToPlay()
mediaPlayerController.moviePlayer.play()
Hope this helps.
FYI, make sure you add the MediaPlayer Framework and add the import MediaPlayer line to the top of your class.

Related

AVPlayer not loading stream url but browser loads it no problem

i need some help with playing stream on really simple ios app which i've made but i can load the stream into the browser and there won't be any problem, but when i try to load it into the ios app its only loading and i don't know what i did wrong.
url of the stream: https://tv1.cdn.netbadgers.com
ViewController.swift
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func playBroadcastClicked(_ sender: Any) {
let videoURL = URL(string: "https://tv1.cdn.netbadgers.com")
let player = AVPlayer(url: videoURL!)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated:true) {
playerViewController.player!.play()
}
}
}
You url is not pointing to a video file, it is actually a HTML page with a video which will never play in the iOS AVPlayer.
Find the direct link to the video, also, make sure the video is in a supported format. If you want a quick solution, just add a WKWebView to your ViewController and then load your url.

Audio not playing after button is clicked

I was following this tutorial on YouTub: https://www.youtube.com/watch?v=qC6DzF_ACpQ&t=714s , and at 12.18 when he clicks the button, it plays audio. I followed all the exact same steps as he did in the video and it is not working for me.
I am pretty new to coding in swift so I did not try anything else other than restarting the whole project again, but it did not work.
import UIKit
import AVFoundation
class ViewController: UIViewController {
var audioPlayer: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func aTapped(_ sender: Any) {
let url = Bundle.main.url(forResource: "a", withExtension: "mp3")
// Make sure that weve got the url, otherwise abord
guard url != nil else{
return
}
do{
audioPlayer = try AVAudioPlayer(contentsOf: url!)
audioPlayer?.play()
}
catch{
print("error")
}
}
I just want the audio to play when I click the button assigned to the code, but when I click the button, no audio plays at all.
Please Help.

How do I perform segue AFTER the sound has stopped playing

I have made a custom LaunchScreen in the Main.Storyboard to make it seem that a sound is actually coming from the LaunchScreen. The sound works fine and the segue to the next view controller as well. The only problem is that the segue happens before the sound has stopped playing. I would like the sound to complete before making the segue. Logically, it should work since the performSegue is directly after the .play(). But it seems that the two happens simultaneously. Here's my code:
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "fanfare", ofType: ".mp3")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound.play() //WORKS
//
DispatchQueue.main.async() {
self.performSegue(withIdentifier: "myLaunchSegue", sender: self) //WORKS
}
I have tried to add:
perform(Selector(("showNavController")), with: self, afterDelay: 3)
where "showNavController" simply is the segue:
func showNavController() {
performSegue(withIdentifier: "myLaunchSegue", sender: nil)
}
but the program crashes with the error "uncaught exception.... ....unrecognized selector sent to instance"
I have also tried to add a boolean to keep the program from progressing until the sound has played, but didn't get it to work. Any ideas?
//////////////////////////
Update:
Trying Russels answer, but have a few questions. Setting AVAudioPlayer as delegate, does that mean setting it next to the class like this:
class MyLaunchViewController: UIViewController, AVAudioPlayer { ...
Also, how do I call the function audioPlayerDidFinishPlaying? Like so:
audioPlayerDidFinishPlaying(musicSound, successfully: true)
I'll post the whole code block. Makes it easier to understand...
import UIKit
import AVFoundation //FOR SOUND
class MyLaunchViewController: UIViewController, AVAudioPlayer {
var musicSound: AVAudioPlayer = AVAudioPlayer() //FOR SOUND
override func viewDidLoad() {
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "fanfare", ofType: ".mp3")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound.play() //WORKS
//
audioPlayerDidFinishPlaying(musicSound, successfully: true)
}
optional func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
DispatchQueue.main.async() {
self.performSegue(withIdentifier: "myLaunchSegue", sender: self)
}
}
I get an error when writing AVAudioPlayer in the class (perhaps I misunderstood what I was supposed to do?). It says I have multiple inheritances. Also, it doesn't want me to set the new function as optional, as its only for protocol members. Finally, If I correct the errors and run the program, the next segue runs before the sound has finished playing... :( sad panda.
You need to make your LaunchScreen an AVAudioPlayerDelegate, and then use the audioPlayerDidFinishPlaying callback. Here's all you need in the first controller
import UIKit
import AVFoundation
class ViewController: UIViewController, AVAudioPlayerDelegate
{
var musicSound: AVAudioPlayer?
override func viewDidLoad() {
super.viewDidLoad()
//PLAY SOUND CLIP//
let musicFile = Bundle.main.path(forResource: "sound", ofType: ".wav")
do {
try musicSound = AVAudioPlayer(contentsOf: URL (fileURLWithPath: musicFile!))
} catch { print("ERROR PLAYING MUSIC")}
musicSound?.delegate = self
musicSound!.play() //WORKS
print("Next line after play")
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
DispatchQueue.main.async() {
print("audioPlayerDidFinishPlaying")
self.performSegue(withIdentifier: "myLaunchSegue", sender: self)
}
}
}
You can get more details here https://developer.apple.com/documentation/avfoundation/avaudioplayerdelegate/1389160-audioplayerdidfinishplaying

Playing Local video with Avplayer/kit Issue

Whenever I run the project, it pulls up the video player, but the video doesn't play
.
How do I fix this? In case the code in the picture isn't clear enough, here is the code:
import UIKit
import AVKit
import AVFoundation
class ViewController: UIViewController {
let avPlayerViewController = AVPlayerViewController()
var avPlayer:AVPlayer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from nib.
let urlPathString = Bundle.main.path(forResource: "small", ofType: "mp4")
if urlPathString != nil {
let movieUrl = NSURL(fileURLWithPath: "/Users/kevingerman/Desktop/Pioneer News Season 2 Episode 1.mp4")
self.avPlayer = AVPlayer(url: movieUrl as URL)
self.avPlayerViewController.player = self.avPlayer
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func playButtonTapped(_ sender: AnyObject) {
//Trigger the video to play
self.present(self.avPlayerViewController, animated: true) { () -> Void in self.avPlayerViewController.player?.play() }
}
}
The solutions suggested in the comment, and the one #Guan has answered are both correct.
Your urlPathString is actually nil here,
To make it work -
1- Either add the Target Membership, as suggested in the comment and the answer above or
Do the following
1.1- Delete the small.mp4 from bundle, make sure you move it to trash
2.1 - Go to trash and drag and drop your mp4 file into the project again, you will get a window like this -
While adding it back make sure you -
Check the projectTarget checkbox like the screenshot below -
Make sure the file name is small.mp4
Make sure your urlPathString is not nil.
I don't know what the following code mean:
let movieUrl = NSURL(fileURLWithPath: "/Users/kevingerman/Desktop/Pioneer News Season 2 Episode 1.mp4")
I think the simulator can not get the path of file which in your mac.(I'm not sure, I haven't do this before).
You can check the file's target membership.
The code may work like this:
var urlPaht = Bundle.main.url(forResource: "small", withExtension:"mp4")
if urlPaht == nil {
urlPaht = NSURL(fileURLWithPath: "/Users/kevingerman/Desktop/Pioneer News Season 2 Episode 1.mp4")
}
self.avPlayer = AVPlayer(url: movieUrl as URL)
self.avPlayerViewController.player = self.avPlayer

Video plays from browser but not on Movie player -SWIFT

Tired of posting questions on SO about the same problem and still not getting solution..If anyone solves this i am gonna award bounty to user afterwards.
I am trying to play video that is on server.A video from the Url(which is commented) gets played but the other dont.What am i doing wrong??
class VideoViewController: UIViewController {
var moviePlayer:MPMoviePlayerController!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
//var url = NSURL(string: "http://devimages.apple.com/iphone/samples/bipbop/gear1/prog_index.m3u8")
//playVideoFromURL(url!)
var url = NSURL(string: "private url")
playVideoFromURL(url!)
}
func playVideoFromURL( address: NSURL ) {
println(address)
var playerVC = MPMoviePlayerViewController(contentURL: address)
playerVC.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
self.presentViewController(playerVC, animated: false, completion: nil)
playerVC.moviePlayer.prepareToPlay()
playerVC.moviePlayer.play()
}
}
Movie player plays the video of the commented ones but doesnot plays the other.What may be the reason for this?
Your code is correct. All you need is to update your info.plist file by adding this key:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
Or you can add it another way and it will look like:

Resources