How to send parameters with AVPlayer request in iOS swift? - ios

I have a POST request where I have to post parameters (track_id , track_name) to url to get a mp3 file content. Now How can i get this mp3 file streaming in AVPlayer?
I know how to stream in AVplayer with an url like :
var player: AVPlayer?
player = AVPlayer(URL: trackURL)
player?.play()
But here my URL won't have any content unless I provide its required parameters (track_id , track_name). How can i set the URL with these 2 parameters?

You need to have the url path to the mp3 resource at the time of initialization. Make the POST request first and then initialize the player with the URL that you get in response.

Related

Twilio: Issue with call record mp3 file in call logs

I'm using this API for getting the Twilio call logs. I want the recording for the corresponding call as an mp3 file. We are accessing recording URLs from the recordings under subresource_uris but that is the .json file. As per this thread, we replaced .json with .mp3 and added https://api.twilio.com at the beginning. If we try to play the recording it is not playing.
Currently, the recording URL is available for all call logs but only a few of the calls have enabled the call record. So how we can distinguish a call is recorded or not?
Twilio developer evangelist here.
From what I can tell, you are trying to access recording files for calls in C#. You can get a list of recordings for a call by requesting the call's recording resource:
string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");
string authToken = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN");
TwilioClient.Init(accountSid, authToken);
var recordings = RecordingResource.Read(
callSid: "CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
limit: 20
);
// print out each recording's URI
foreach(var record in recordings)
{
Console.WriteLine(record.Uri);
}
If you run the above with a call Sid that has recordings then you will see the URIs of the recording's printed out. They will look like:
/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Recordings/REXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.json
This is the URI you should take, prefix with https://api.twilio.com and change the extension from .json to .mp3 in order to get the recording file. So, for the above example, requesting:
https://api.twilio.com/2010-04-01/Accounts/ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Recordings/REXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.mp3
So, if you use the API to get the call logs to get the Call SIDs, then call on each call's recordings resource you can then get the list of recordings and construct the URI to download each recording audio file.

how to get youtube live api stream key

How can I bind my YouTube stream key to match previous video.
I'm trying to use java to do it but getting no where.
I'm looking at the example given to create the broadcast stream but it doesn't have the keeping same key.
I've gotten help on this before. Please try do some research on Google and then ask the question. You can see How can I change the stream my event uses via the YouTube live api?. Which will help you as it did me.
In short this was the code i received for help.
Credit to #M. Prokhorov
YouTube yt = ... // your reference to YouTube
String broadcastId = ... // your broadcast Id
String newStreamId = ... // identifier of stream you want to bind
String apiKEy = ... // your API key
// you can define other response parts if you want more or don't want some of these
String responseParts = "id,status,contentDetails.boundStreamId";
yt.liveBroadcasts().bind(broadcastId, responseParts)
.setApiKey(apiKey)
.setStreamId(streamId)
// other data you might want in request
.execute()

Playing Offline HLS with AES-128 encryption iOS

I want to integrate offline HLS in iOS through AVFoundation.
I have an encrypted HLS with simple AES-128 and it doesn't want to play in offline mode, I was trying to integrate AVAssetResourceLoaderDelegate, but don't know how to integrate applicationCertificate and contentKeyFromKeyServerModuleWithSPCData that are in https://developer.apple.com/streaming/fps/ examples. I have a feeling that I am doing something wrong. It is a sample AES-128 encryption, not even DRM.
Without the internet, AVPlayer is still trying to get encryption key through GET request.
It would be great if someone succeeded to save the encrypted key locally and somehow gave it to AVPlayer together with AVURLAsset.
Did someone manage to integrate this?
I have written to apple support and their responses weren't new for me. Information that they provided to me I got from wwdc videos and documentation before I started a conversation with them. (https://developer.apple.com/streaming/fps/)
Further, I will describe how I achieve to play HLS in offline mode with AES-128 encryption. The Example On Github describes the below process.
Take care AVDownloadTask doesn’t work on the simulator so you should have a device for this implementation.
At the beginning, you need a stream URL.
Step 1:
Before creating AVURLAsset we should take stream URL and change scheme to an invalid one (example: https -> fakehttps, I did it through URLComponents) and assign AVAssetResourceLoaderDelegate to the new created url asset. All this changes force AVAssetDownloadTask to call:
func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
}
(it is calling because AVFoundation see an invalid URL and doesn’t know what to do with it)
Step 2:
When delegate is called we should check that url is that one that we had before. We need to change back scheme to valid one and create a simple URLSession with it. We will get first .m3u8 file that should be like:
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1697588,RESOLUTION=1280x720,FRAME-RATE=23.980,CODECS="mp4a"
https://avid.avid.net/avid/information_about_stream1
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1132382,RESOLUTION=848x480,FRAME-RATE=23.980,CODECS="mp4a"
https://avid.avid.net/avid/information_about_stream2
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=690409,RESOLUTION=640x360,FRAME-RATE=23.980,CODECS="mp4a"
https://avid.avid.net/avid/information_about_stream3
Step 3:
Parse all needed information from this data and change all https schemes to invalid one fakehttps
Now you should setup AVAssetResourceLoadingRequest from shouldWaitForLoadingOfRequestedResource delegate like:
loadingRequest.contentInformationRequest?.contentType = response.mimeType
loadingRequest.contentInformationRequest?.isByteRangeAccessSupported = true
loadingRequest.contentInformationRequest?.contentLength = response.expectedContentLength
loadingRequest.dataRequest?.respond(with: modifiedData)
loadingRequest.finishLoading()
downloadTask?.resume()
where: response -> response from URLSession, modifiedData -> data with changed URL’s
Resume your download task and return true in shouldWaitForLoadingOfRequestedResource delegate
Step 4:
If everything will be ok AVAssetDownloadDelegate will fire with:
- (void)URLSession:(NSURLSession *)session assetDownloadTask:(AVAssetDownloadTask *)assetDownloadTask didResolveMediaSelection:(AVMediaSelection *)resolvedMediaSelection NS_AVAILABLE_IOS(9_0) {
}
Step 5:
We have changed all https to fakehttps when AVFoundation will select best media stream URL, shouldWaitForLoadingOfRequestedResource will trigger again with one of the URL from first .m3u8
Step 6:
When delegate is called again we should check that url is that one that we needed. Change again fake scheme to a valid one and create a simple URLSession with this url. We will get second .m3u8 file:
#EXTM3U
#EXT-X-TARGETDURATION:12
#EXT-X-ALLOW-CACHE:YES
#EXT-X-KEY:METHOD=AES-128,URI="https://avid.avid.net/avid/key”
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:1
#EXTINF:6.006,
https://avid.avid.net/avid/information_about_stream1
#EXTINF:4.713,
https://avid.avid.net/avid/information_about_stream2
#EXTINF:10.093,
https://avid.avid.net/avid/information_about_stream3
#EXT-X-ENDLIST
Step 7:
Parse second .m3u8 file and take all information that you need from it, also take a look on
#EXT-X-KEY:METHOD=AES-128,URI="https://avid.avid.net/avid/key”
We have URL for encryption key
Step 8:
Before sending some information back to AVAssetDownloadDelegate we need to download the key from the server and save it locally on the device. After this you should change URI=https://avid.avid.net/avid/key from second .m3u8 to an invalid URI=fakehttps://avid.avid.net/avid/key, or maybe a local file path where you have saved your local key.
Now you should setup AVAssetResourceLoadingRequest from shouldWaitForLoadingOfRequestedResource delegate smth. like:
loadingRequest.contentInformationRequest?.contentType = response.mimeType
loadingRequest.contentInformationRequest?.isByteRangeAccessSupported = true
loadingRequest.contentInformationRequest?.contentLength = response.expectedContentLength
loadingRequest.dataRequest?.respond(with: modifiedData)
loadingRequest.finishLoading()
downloadTask?.resume()
where: response -> response from URLSession, modifiedData -> data with changed URL’s
Resume your download task and return true in shouldWaitForLoadingOfRequestedResource delegate (Same as on Step 3)
Step 9:
Of course, when download task will try to create request with modified URI= that again is not a valid one shouldWaitForLoadingOfRequestedResource will trigger again. In this case, you should detect this and create new data with your persistent key(the key that you saved locally. Take care here contentType should be AVStreamingKeyDeliveryPersistentContentKeyType without it AVFoundation doesn’t understand that this contains key).
loadingRequest.contentInformationRequest?.contentType = AVStreamingKeyDeliveryPersistentContentKeyType
loadingRequest.contentInformationRequest?.isByteRangeAccessSupported = true
loadingRequest.contentInformationRequest?.contentLength = keyData.count
loadingRequest.dataRequest?.respond(with: keyData)
loadingRequest.finishLoading()
downloadTask?.resume()
Step 10:
Chunks will be downloaded automatically by AVFoudnation.
When download is finished this delegate will be called:
func urlSession(_ session: URLSession, assetDownloadTask: AVAssetDownloadTask, didFinishDownloadingTo location: URL) {
}
You should save location somewhere, when you want to play stream from device you should create AVURLAsset from this location URL
All this information is saved locally by AVFoundation so next time when you will try to play local content in offline AVURLAsset delegate will be called because of URI=fakehttps://avid.avid.net/avid/key, that is an invalid link, here you will do Step 9 again and video will play in offline mode.
This works for me if anyone knows better implementation I will be glad to know.
Example On Github
#Cyklet Answer helped me a ton! Thanks.
There is however an additional step I had to do to get hls streaming to work.
When using shouldWaitForLoadingOfRequestedResource apples documentation states:
contentType
Before finishing loading an AVAssetResourceLoadingRequest instance, if its contentInformationRequest property is not nil, set the value of this property to a UTI indicating the type of data contained by the requested resource.
When trying to implement HLS Streaming there are two UTIs that may be used (as far as I know...).
AVStreamingKeyDeliveryPersistentContentKeyType
"com.apple.streamingkeydelivery.persistentcontentkey"
AVStreamingKeyDeliveryContentKeyType
"com.apple.streamingkeydelivery.contentkey"
Check allowedContentTypes what UTI to use. See possible implementation below:
func resourceLoader(_ resourceLoader: AVAssetResourceLoader, shouldWaitForLoadingOfRequestedResource loadingRequest: AVAssetResourceLoadingRequest) -> Bool {
....
var contentType = AVStreamingKeyDeliveryPersistentContentKeyType
if let allowedContentType = contentInformationRequest.allowedContentTypes?.first{
if allowedContentType == AVStreamingKeyDeliveryContentKeyType{
contentType = AVStreamingKeyDeliveryContentKeyType
}
}
....
}

Play a protected video content in iOS using AVPlayer

im trying to play a protected video which you need to be logged thru our API and get a cookie to access to the m3u8. In Safari, i need to be logged in in order to play the video. I tried to implement this but doesnt work at all.
let cookies: [Any] = HTTPCookieStorage.shared.cookies!
self.playerAsset = AVURLAsset.init(url: urlStream!, options:[AVURLAssetHTTPCookiesKey : cookies])
let item = AVPlayerItem(asset: self.playerAsset!)
self.playerItems.append(item)
Anyone could help me ?
could you play the video in saffari? If yes then you can use the new safari webview instead of avplayer

mp4 video on iOS app using Swift

I've been looking at other posted questions regarding playing videos from websites and none of the solutions have worked for me. I get a black screen when I test my app, and the video doesn't seem to ever load.
Globally, I have declared:
var moviePlayer:MPMoviePlayerController!
And within my ViewDidLoad() function, I have:
let url:NSURL = NSURL(string:"http://uapi-f1.picovico.com/v2.1/v/nMirP/ArwenUndomiel.mp4")!
self.moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = self.moviePlayer {
player.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
player.view.sizeToFit()
player.scalingMode = MPMovieScalingMode.None
player.movieSourceType = MPMovieSourceType.Streaming
self.view.addSubview(player.view)
player.play()
}
Thanks for the help!
The URL that Picovico have given you actually responds with a message telling the requester that the content is not at this location but that they should try a different location - this is a common technique for URL redirecting.
You can see this if you try the link in a browser and capture the network request and responses. For example using the link you include above in Chrome gives this response:
You can see that the server is telling the client (browser in this case) to redirect (i.e. send a new request) to an S3 amazon URL which is where your video actually has been stored by Picovico.
When the browser then sends it's request to that location it finds the video successfully:
Looking at your video using ffprobe the format seems fine so it seems likely that the iOS client is having a hard time handling the redirect, or else that there was an issues with the URL redirection temporarily on Picovico's servers. If you still have the problem now then the former is most likely the problem.
If you take a look here you can see how someone has solved the problem of iOS media player handling redirects:
iOS Mediaplayer and URL redirection

Resources