I have been using AVKit to stream a video, below is the code I am using to stream videos in TVOS. But the problem is I am unable to do the same with the Dropbox Link? Is a Dropbox API integration required for this?
func _viewVideo(_ url: Foundation.URL)
{
let url = Foundation.URL(string: "http://techslides.com/demos/sample-videos/small.mp4")
let asset = AVURLAsset(url: url)
let item = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: item)
playerViewController?.player = player
playerViewController?.view.frame = CGRect(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height)
playerViewController?.showsPlaybackControls = true
self.view.addSubview((playerViewController?.view)!)
player.play()
}
You can stream videos from Dropbox share links in Apple TV, however, you need to make a tiny change in the link.
You need to force a file to download in your link, just change the end of the link from dl=0 to dl=1. In this way, Apple TV can stream videos from Dropbox share links.
For reference: Force a file or folder to download, or to render on dropbox.com
Related
We have successfully configured Subtitles/Captions in Azure Media Player which plays media on the Web side.
But, how do we configure the same for playing the media managed by AMS in iOS for Native AVPlayer? We know that captions/subtitles can be played in native iOS player with Sidecar WebVTT file, but is the "transcript.vtt" file generated by AMS, the Sidecar WebVTT file ?
If not, how do we generate the sidecar WebVTT file?
We have implemented the code as below with Media file being accessed from AMS link and a locally downloaded transcript.vtt file, but it fails.
[EDITED : 20200413]
However, when we have local media file and local transcript.vtt file, or when we directly access the media file in the media storage account (https://mediastorageaccount.blob.core.windows.net/container/file.mp4) it works fine. But, when we access the encoded file from the link generated by AMS Transform (https://mediaservice-inct.streaming.media.azure.net/788888-6666-4444-aaaa-823422j218/file.ism/manifest(format=m3u8-cmaf)) it fails.
What is wrong here?
func playVideo()
{
let strUrl = "https://mediaservice-inct.streaming.media.azure.net/79510-6eb-340-a90-824218/German-FAST_Lesson-2-Dialog.ism/manifest(format=m3u8-cmaf)"
localVideoAsset = AVURLAsset(url: URL(string: strUrl)!)
//We have to add tracks in AVMutableComposition same like bellow
//First we have to add video track on AVMutableComposition
let videoTrack = videoPlusSubtitles.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
do{
guard localVideoAsset!.tracks.count > 0 else{
// error msg
return
}
try? videoTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: localVideoAsset!.duration),
of:localVideoAsset!.tracks(withMediaType: .video)[0],
at: seconds)
}
//After that we have to add subtitle track in AVMutableComposition
if isEnglishSubtitle {
setSubtitleTrack(subtitle: "transcript")
}else{
setSubtitleTrack(subtitle: "transcript_tr")
}
//After set the video track and subtitle track we have to set in the player same like bellow
player = AVPlayer(playerItem: AVPlayerItem(asset: videoPlusSubtitles))
playerLayer.removeFromSuperlayer()
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.videoView.bounds
playerLayer.videoGravity = .resizeAspect
self.videoView.layer.addSublayer(playerLayer)
player.play()
}
func setSubtitleTrack(subtitle : String){
print(subtitle)
print(seconds)
//Here we have to check if any pre track available. If available then we have to remove it same like bellow
if subtitleTrack != nil{
videoPlusSubtitles.removeTrack(subtitleTrack!)
}
//We have to get subtitle file from path same like bellow
let subtitleAsset = AVURLAsset(url: Bundle.main.url(forResource: subtitle, withExtension: ".vtt")!)
// And we have to add new track from here
subtitleTrack = videoPlusSubtitles.addMutableTrack(withMediaType: .text, preferredTrackID: kCMPersistentTrackID_Invalid)
do{
guard subtitleAsset.tracks.count > 0 else{
//error msg
return
}
try? subtitleTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: localVideoAsset!.duration),
of:subtitleAsset.tracks(withMediaType: .text)[0],
at: seconds)
}
}
I suspect the issue is not caused by the AMS stream. To double check, you may want to try using another stream HLS(e.g. try a HLS provided by Apple). Apple has specific requirements for playing VTT in AVPlayer. I've included an Apple doc link which has a lot of examples on streaming, and other links that may be helpful:
https://developer.apple.com/streaming/examples/
How to add external .vtt subtitle file to AVPlayerViewController in tvOS
AVUrlAsset and WebVTTs
I work on an iOS app that bring videos and images from server, each object have many images and videos, I need to show these images and videos in a slider (pager) where user can slide to get the next one, and I need these videos and images cached in device, I google that and I found this pod but it not play video which is a few seconds infinitely, and I try to play the provided video URL in example of pod and it's also have the same issue, are there any alternative solution or any solution for this pod?
First of all create a UIView outlet for display image or Video then you can use this code `
let avPlayer = AVPlayer()
let videolink = (videosString[indexPath.row] as? String)!
let videoURL = NSURL(string: videolink)
avPlayer = AVPlayer(url: videoURL! as URL)
let playerLayer = AVPlayerLayer(player: avPlayer)
playerLayer.frame = CGRect(x: cell.videoview.frame.origin.x, y: cell.videoview.frame.origin.x, width: cell.videoview.frame.size.width, height: cell.videoview.frame.size.height)
cell.videoview.layer.addSublayer(playerLayer)
avPlayer.play()`
like videoVideo is a view where you wish to play a video(avplayer will add a layer to that view)
To present Image, you can use SKPhotoBrowser
to differentiate Image and Video you can use bool
Hope you got it
If you need any help ask me i can code for you
Since iOS 10, Apple has provided the support for downloading HLS (m3u8) video for offline viewing.
My question is: Is it necessary that we can only download HLS when it is being played ? Or we can just download when user press download button and show progress.
Does anyone has implemented this in Objective C version? Actually my previous App is made in Objective C. Now I want to add support for downloading HLS rather than MP4 (previously I was downloading MP4 for offline view).
I am really desperate to this. Please share thoughts or any code if implemented.
I used the apple code guid to download HLS content with the following code:
var configuration: URLSessionConfiguration?
var downloadSession: AVAssetDownloadURLSession?
var downloadIdentifier = "\(Bundle.main.bundleIdentifier!).background"
func setupAssetDownload(videoUrl: String) {
// Create new background session configuration.
configuration = URLSessionConfiguration.background(withIdentifier: downloadIdentifier)
// Create a new AVAssetDownloadURLSession with background configuration, delegate, and queue
downloadSession = AVAssetDownloadURLSession(configuration: configuration!,
assetDownloadDelegate: self,
delegateQueue: OperationQueue.main)
if let url = URL(string: videoUrl){
let asset = AVURLAsset(url: url)
// Create new AVAssetDownloadTask for the desired asset
let downloadTask = downloadSession?.makeAssetDownloadTask(asset: asset,
assetTitle: "Some Title",
assetArtworkData: nil,
options: nil)
// Start task and begin download
downloadTask?.resume()
}
}//end method
func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didFinishDownloadingTo location: URL) {
// Do not move the asset from the download location
UserDefaults.standard.set(location.relativePath, forKey: "testVideoPath")
}
if you don't understand what's going on, read up about it here:
https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MediaPlaybackGuide/Contents/Resources/en.lproj/HTTPLiveStreaming/HTTPLiveStreaming.html
now you can use the stored HSL content to play the video in AVPlayer with the following code:
//get the saved link from the user defaults
let savedLink = UserDefaults.standard.string(forKey: "testVideoPath")
let baseUrl = URL(fileURLWithPath: NSHomeDirectory()) //app's home directory
let assetUrl = baseUrl.appendingPathComponent(savedLink!) //append the saved link to home path
now use the path to play video in AVPlayer
let avAssest = AVAsset(url: assetUrl)
let playerItem = AVPlayerItem(asset: avAssest)
let player = AVPlayer(playerItem: playerItem) // video path coming from above function
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true, completion: {
player.play()
})
The only way you can do this is to set up an HTTP server to serve the files locally after you've downloaded them.
The Live playlist uses a sliding-window. You need to periodically reload it after target-duration time and download only the new segments as they appear in the list (they will be removed at a later time).
Here are some related answers: Can IOS devices stream m3u8 segmented video from the local file system using html5 video and phonegap/cordova?
You can easily download an HLS stream with AVAssetDownloadURLSession makeAssetDownloadTask. Have a look at the AssetPersistenceManager in Apples Sample code: https://developer.apple.com/library/content/samplecode/HLSCatalog/Introduction/Intro.html
It should be fairly straight forward to use the Objective C version of the api.
Yes, you can download video stream served over HLS and watch it later.
There is a very straight forward sample app (HLSCatalog) from apple on this. The code is fairly simple. you can find it here - https://developer.apple.com/services-account/download?path=/Developer_Tools/FairPlay_Streaming_Server_SDK_v3.1/FairPlay_Streaming_Server_SDK_v3.1.zip
You can find more about offline HLS streaming here.
I am currently working on HTTP Live streaming video with AVPlayerViewController / AVPlayer
i am play a video with .m38u file supported
It playing fine but my question is that can i have the data of video like i have set 4 type of resolution while genrating the .m38u file.. , i can varies the resoltion at my end point now the question is how to get the all values which i have setup at my endpoint. I am play this is in android also and using Track i am able to fetch all the video information but in ios how can i fetch all the details containing the video like its height , with, track,resolution supported by video etc..
I have search alot but could not get succeed..
Need help
Thanks in advance
Anita, I start I hope here is slice of code for playing a VIDEO..
self.command.text = "Loading VIDEO"
let videoURL = self.currentSlide.aURL
self.playerItem = AVPlayerItem(URL: videoURL)
self.player = AVPlayer(playerItem: self.playerItem)
self.playerLayer = AVPlayerLayer(player: self.player)
self.streamPlayer = AVPlayerViewController()
self.streamPlayer.player = self.player
self.streamPlayer.view.frame = CGRect(x: 128, y: 222, width: 512, height: 256)
let currentFM = self.streamPlayer.player?.currentItem?.asset
for blah in (currentFM?.metadata.enumerate())! {
print("blah \(blah)")
}
self.presentViewController(self.streamPlayer, animated: true)
self.streamPlayer.player!.play()
}
I added a little extra for showing meta data about the video... it printed...
blah (0, <AVMetadataItem: 0x15e7e4280, identifier=itsk/gsst, keySpace=itsk, key class = __NSCFNumber, key=gsst, commonKey=(null), extendedLanguageTag= (null), dataType=com.apple.metadata.datatype.UTF-8, time={INVALID}, duration= {INVALID}, startDate=(null), extras={
dataType = 1;
dataTypeNamespace = "com.apple.itunes";
}, value=0>)
blah (1, <AVMetadataItem: 0x15e7e1a50, identifier=itsk/gstd, keySpace=itsk, key class = __NSCFNumber, key=gstd, commonKey=(null), extendedLanguageTag=(null), dataType=com.apple.metadata.datatype.UTF-8, time={INVALID}, duration={INVALID}, startDate=(null), extras={
dataType = 1;
dataTypeNamespace = "com.apple.itunes";
}, value=222980>)
Hopefully it means a lot more to you than it does to me :) What your looking I think is classed/called metadata in Applespeak...
Take a look at this post too
Capture still image from AVCaptureSession in Swift
It describes how-to capture a frame of your video, once you have a frame you can take a closer look at its meta data and I suspect find out some of the details you seek.
let metadata = info[UIImagePickerControllerMediaMetadata] as? NSDictionary
let image = info[UIImagePickerControllerOriginalImage] as? UIImage
Are the commands to try and fetch that... let me know if you manage to succeed!
I am attempting to play a video by using a data URI (data:video/mp4;base64,AAAAHGZ0eXBtcDQyAAAAAG1wNDJpc29......). Here is my code thus far:
func videoDataWasLoaded(data: NSData) {
let moviePlayer = MPMoviePlayerController()
let base64 = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let dataUri = NSURL(string: "data:video/mp4;base64,\(base64)")
moviePlayer.contentURL = dataUri
moviePlayer.play()
}
I have confirmed that the video plays by writing the data (NSData) to a tmp file and then using that for the contentURL. However, writing to disk is slow, and I figured that the data URI approach would be faster especially since my movie files are small (around 5 seconds each).
UPDATE: This question is not so much concerned about which method (AVPlayer, MPMoviePlayerController) is used to play the video. Rather, it is concerned with the possibility of playing a video from a data URI. Here is a link which describes what I am wanting to do in terms of HTML5.
This code plays a movie from a URL ... assuming that is your question?
let videoURL = self.currentSlide.aURL
self.playerItem = AVPlayerItem(URL: videoURL)
self.player = AVPlayer(playerItem: self.playerItem)
self.playerLayer = AVPlayerLayer(player: self.player)
self.streamPlayer = AVPlayerViewController()
self.streamPlayer.player = self.player
self.streamPlayer.view.frame = CGRect(x: 128, y: 222, width: 512, height: 256)
self.presentViewController(self.streamPlayer, animated: true) {
self.streamPlayer.player!.play()
}
But sorry, that is to play a URL; you want an URI. I though you had mis-typed your question, my error. I looked up URI this time :|
The answer must surely lie in the conversion of your video source to a playable stream, as in an M3u8. Here is an excellent post on the subject it seems.
http://stackoverflow.com/questions/6592485/http-live-streaming