Free hosting video platform compatible with AVPlayer support - ios

I am trying to play a video from my iOS app when tapping a button, but I was wondering how and where I can host my video (for free) so that I can play the video in an AVPlayer using the URL. I tried hosting the video on youtube, and setting the AVPlayer URL to the youtube video URL, but the player loads forever. I included my code, it's functional, I just need to know where I can upload my video to get a proper URL.
#IBAction func didTapPlayButton(_ sender: UIButton) {
guard let url = URL(string: "") else {
return
}
// Create an AVPlayer, passing it the HTTP Live Streaming URL.
let player = AVPlayer(url: url)
// Create a new AVPlayerViewController and pass it a reference to the player.
let controller = AVPlayerViewController()
controller.player = player
// Modally present the player and call the player's play() method when complete.
present(controller, animated: true) {
player.play()
}
}

You need to host and serve your video as a binary file.
You can use an object storage (e.g. Firebase Storage or AWS S3) or serve the file through a web API.
Just set the correct Content-Type (e.g. "video/mp4" to help the player recognise the binary file type)
You can then initiate your AVPlayer with the URL of the video.
Please note that Firebase Storage has a very generous free tier, it might be all you need.
For example:
You can take a look at this video file:
https://file-examples.com/wp-content/uploads/2017/04/file_example_MP4_480_1_5MG.mp4
This file is hosted as a binary and the Content-Type is set to video/mp4.
Try to initiate your AVPlayer with the above URL and see that it works.

Related

An online mp3 AVPlayerItem that failed to play will never play again

I am having trouble playing online mp3 files as AVPlayerItems which have previously failed to play due to data connection issues.
For example:
I try play online mp3 file "FILE_A" with poor data connection and the associated AVPlayerItem fails to play. The AVPlayerItem will then not load and my AVPlayer will stay paused (which is fine for now).
Let's say that after a period of time I gain better data connection and play a different online mp3 file "FILE_B" as an AVPlayerItem. The AVPlayer plays this AVPlayerItem with no issues.
I then try play the failed file "FILE_A" on good data connection. The AVPlayerItem for "FILE_A" will always refuse to play. I can even close/kill the app and try again and "FILE_A" will not play. The only work around is to do a fresh re-install of the app.
I have 3 questions:
Why does a failed AVPlayerItem never become playable, is there a AVPlayerItem cache in the AVPlayer that always tries to play the failed item?
Is there a way to refresh an unplayable AVPlayerItem to make it play again?
What is the best way to deinitialize an AVPLayer? Currently I am using self.player = nil to deinitialize the player in the deint of my view controller or when a user logs out of their account in the app.
This is how I set up the AVPlayer:
self.player = AVPlayer()
self.player?.actionAtItemEnd = .pause
self.player?.automaticallyWaitsToMinimizeStalling = false
self.player?.addObserver(self, forKeyPath: "status", options: .new, context: nil)
This is how I set up an AVPlayerItem and set it as the AVPlayer's currentItem:
let url = URL(string: onlineAudioFileUrl)
currentPlayerItem = AVPlayerItem(url: url)
player?.replaceCurrentItem(with: currentPlayerItem)
The onlineAudioFileUrl above is String url representing the url of an online mp3 file stored on a server. It has the form:
https://ourserver.com/audio_file_name.mp3?Expires=NUMERIC_EXPIRE_TIME&Key-Pair-Id=KEY_PAIR_ID_STRING&Signature=VERY_LONG_SIGNATURE_STRING

How to play audio files from Google Drive (Swift 5)

In my project I use a Google Drive API. I get a list of the user's files and can save them to the device memory.
I also want to be able to play audio files directly from Google Drive, but I just can't do it. The AVPlayer doesn't want to play the audio file using the URL link, which I transfer to him. But if I paste this link into any browser, then the track is played.
Has anyone encountered this and knows how to fix the problem? I would be grateful for any help.
My code looks like this (it's a simplified version):
import AVKit
class MyVC: UIViewController {
...
var player: AVPlayer!
...
private func playTrack() {
let url = URL(string: "https://drive.google.com/uc?export=open&id=XXXXX" //where XXXXX is an item id
let playerItem: AVPlayerItem = AVPlayerItem(url: url!)
player = AVPlayer(playerItem: playerItem)
player!.play()
}
}
For example URL link which I transfer to the AVPlayer looks like this:
https://drive.google.com/uc?export=open&id=1JzuAhQ-7R01wLhtD8zEN_sC5nvFlt7wU
But if I paste it into the browser it automatically changes and looks like this:
https://doc-0g-1s-docs.googleusercontent.com/docs/securesc/anu2dlv0j1ugsoh1pb6b8qpkkt7k1j6k/hp3dnmru336i1cpkk4f5p4bstc83b30f/1602827400000/02426681720429398713/02426681720429398713/1JzuAhQ-7R01wLhtD8zEN_sC5nvFlt7wU?e=open&authuser=0&nonce=4dd9dhoo6he8g&user=02426681720429398713&hash=o87f0k3t4iv19ugae899urmcjd14ogiq
Maybe it's important.
You files should be shared by a direct link in Google Drive to play it so you can make it manually or using API e.g.:
And then use direct links in format: https://drive.google.com/uc?export=open&id=XXXXX.

Hls stream url wont play in AVPlayer

I am trying to play an hls live stream from a url that looks like this: "http://ip.address:port/my%20video.m3u8". Whenever the url does not involve any spaces the video plays fine otherwise it does not play. There is no error logged from the player but the player itself is just a black screen. I enabled "Allow Arbitrary Loads" and still no dice. When I try loading the urls with spaces in safari the video will play. Here is my code to load and play the video:
DispatchQueue.main.async {
var player = AVPlayer(url: url!)
var playerLayer: AVPlayerLayer!
playerLayer = AVPlayerLayer(player: player)
playerLayer.videoGravity = .resize
self.videoView.layer.addSublayer(playerLayer)
playerLayer.frame = self.videoView.bounds
player.play()
}
What I also find odd is when I try sending the stream to a AVPlayerViewController the player pops up but does not play. Here is how I am sending it to the view controller:
DispatchQueue.main.async {
let player = AVPlayer(url: urlTwo)
let playerController = AVPlayerViewController()
playerController.player = player
present(playerController, animated: true) {
player.play()
}
}
Please check the m3u8 file may be the content in m3u8 have some directory issue. .ts segment and .key file was mentioned in m3u8 file. And when you pass m3u8 to avplayer it fetch the key and .ts file automatically and decrypt the .ts with the mentioned key. Just cross check you m3u8 for key and .ts file.
Also, .key and .ts files need to be in same folder along with m3u8 otherwise it will not fetch and player keep looking for the key and ts.
#EXTM3U
#EXT-X-TARGETDURATION:12
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-VERSION:4
#EXT-X-KEY:METHOD=AES-128,URI="title.key"
#EXTINF:10.0100,
#EXT-X-BYTERANGE:943584#0
title.ts
Something like this.
Note: Sometimes m3u8 and key file have additional encryption which you need to decrypt on run time. I suggest open it in text editor and see if you can see something like given structure above. If it has something unreadable then you need to decrypt it first on run time. If you are using local server and loading file from cache then save the m3u8 file after decryption with Encoding.utf8 and .key file with Encoding.macOSRoman. Otherwise it will not gonna work. Cheers.

Play IOS Music Library Content Using AVFoundation

I'm attempting to write an IOS app that will play my iPhone music library content, showing artwork, and "announcing" title, artist, etc.
I have it working nicely using Apple's Media Player framework. I can display Playlist names and queue the songs in a selected Playlist.
I use the "MPMusicPlayerControllerNowPlayingItemDidChange" observer notification to pause playback, retrieve metadata, and do the announcements via AVSpeechSynthesizer.
I was a happy camper until I ran into the dreaded "Media Player framwork doesn't respond to observer notifications in background" issue.
So, I started looking at the AVFoundation Framework. I found a sample that plays local song files via URLs in the background and.
I'm failing miserably in attempting to retrieve Music Library content via the AVFoundation.
I have also failed in supplying content retrieved via the Media Player framework to the AVFoundation player.
(Note: The URLs retrieved from MPMediaItem are of a bogus "ipod-library://item/item.m4a?id=#########################" format. Creating AVPlayerItem with this "URL" doesn't work.)
Has anyone managed to accomplish this? I'm developing for my own usage. I have no intention of posting the app in Apple's App Store, so I'm willing to use hidden APIs or un-Apple approved methodology.
A Swift code example would be great. (Objective-C not so much)
Having fetched an MPMediaItem from the user's library, obtain its assetURL. Creating an AVPlayer from the resulting URL does work.
Actual code from one of my example apps:
func oneSong () -> (URL?, String?) {
let query = MPMediaQuery.songs()
// always need to filter out songs that aren't present
let isPresent = MPMediaPropertyPredicate(value:false,
forProperty:MPMediaItemPropertyIsCloudItem,
comparisonType:.equalTo)
query.addFilterPredicate(isPresent)
let item = query.items?[0]
return (item?.assetURL, item?.title)
}
#IBAction func doPlayOneSongAVPlayer (_ sender: Any) {
let (url, title) = self.oneSong()
if let url = url, let title = title {
self.avplayer = AVPlayer(url:url)
self.avplayer.play()
MPNowPlayingInfoCenter.default().nowPlayingInfo = [
MPMediaItemPropertyTitle : title
]
}
}

To play Youtube Video in iOS app

I want to play youtube videos in my iOS App. I searched for that but the only solution I found is to embed youtube videos in the iOS app, in which video plays in webview, so in that, we can scroll and also play other videos which are in suggestion.
I don't want to play video in webview, I want to play video just like it plays in player and user cannot scroll it.
Is there any solution for that in Swift and also I don't want to use libraries which are against terms and condition of Youtube
Here's another solution if you don't want to use the API provided by YouTube and instead continue using a UIWebView.
YouTube has functionality to load any video in fullscreen in a webview without any of the scrolling features using a URL in the format https://www.youtube.com/embed/<videoId>.
For example, to load Gangnam Style using this method, simply direct the UIWebView to the URL https://www.youtube.com/embed/9bZkp7q19f0.
The API that YouTube provides to embed videos in iOS apps is indeed written in Objective-C, but it works just as well in Swift.
To install the library via CocoaPods, follow the CocoaPods setup instructions and add the following line to your Podfile:
pod ‘youtube-ios-player-helper’, ‘~> 0.1’
Once you have run pod install, be sure to use the .xcworkspace file from now on in Xcode.
To import the pod, simply use the following import statement at the top of your Swift files:
import youtube_ios_player_helper
You can then create youtube player views as follows:
let playerView = YTPlayerView()
You can include this view in your layouts as you would any other UIView. In addition, it includes all of the functions listed in the YouTube documentation. For instance, to load and play a video, use the following function:
playerView.load(withVideoId: videoId);
Where videoId is the string id found in the URL of the video, such as "9bZkp7q19f0".
There also are solutions for playing Youtube Videos in an app on Github.
Like this one: https://github.com/rinov/YoutubeKit
Or this one: https://github.com/gilesvangruisen/Swift-YouTube-Player
Just simply add the pod for the project that you want to use, install the pod in terminal, and you can use the functionality in that project.
Hope that this is helpful.
Play youtube video in Swift 4.0
if let range = strUrl.range(of: "=") {
let strIdentifier = strUrl.substring(from: range.upperBound)
let playerViewController = AVPlayerViewController()
self.present(playerViewController, animated: true, completion: nil)
XCDYouTubeClient.default().getVideoWithIdentifier(strIdentifier) {
[weak playerViewController] (video: XCDYouTubeVideo?, error: Error?) in
if let streamURLs = video?.streamURLs, let streamURL =
(streamURLs[XCDYouTubeVideoQualityHTTPLiveStreaming] ??
streamURLs[YouTubeVideoQuality.hd720] ??
streamURLs[YouTubeVideoQuality.medium360] ??
streamURLs[YouTubeVideoQuality.small240]) {
playerViewController?.player = AVPlayer(url: streamURL)
} else {
self.dismiss(animated: true, completion: nil)
}
}
}

Resources