I have an iOS app that streams video on iPhone/iPad devices.
Now I need to get the bitrate on video streaming on the iPhone/iPad device.
ObservedBitrate and IndicatedBitrate does not help with this.
I also came across this below post but few comments mention it works for mpeg4 videos only.
How to check Resolution, bitrate of video in iOS
I'm looking for the bitrate of video streaming on iPhone/iPad and for any video format.
Thanks!
You can listen for AVPlayerItemNewAccessLogEntry notification to get current bitrates for your stream such as:
observedBitrate - aka your current download speed
indicatedBitrate - comes from m3u8 (BANDWIDTH) and means a min bitrate value to play your current stream
Adaptive video playback with AVPlayer can change a current stream to a stream with high or low bandwidth back and forth by network conditions but these changes do not appears on every stalls, network issues etc. because your steam can be buffered, m3u8 doesn't have stream with lower bandwidth to play etc. So if you need to detect a current realtime playback state look to stalls, FPS.
There is sample code in swift but it's easy convertible to objc if you need:
let url = URL(string: "https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8")!
let playerItem = AVPlayerItem(url: url)
self.player = AVPlayer(playerItem: playerItem)
NotificationCenter.default.addObserver(forName: .AVPlayerItemNewAccessLogEntry, object: playerItem, queue: nil) { notification in
if let event = playerItem.accessLog()?.events.last {
let bitrates = [event.observedBitrate,
event.indicatedBitrate,
event.averageVideoBitrate,
]
print(">", bitrates)
}
}
player?.play()
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = view.bounds
view.layer.addSublayer(playerLayer)
Outputs:
> [16375938.865617642, 628000.0, 307568.0]
> [nan, 1728000.0, 0.0]
> [9830221.39078689, 2528000.0, 1422032.0]
Related
I am developing an iOS app in Swift that plays audio files on TV over Google Cast.
App uses two-way communication over TextChannel to exchange information with the receiver app.
The app is working as expected until I put the app into the background. After the app is backgrounded the Google Cast session gets disconnected.
To ensure app is not susspended in the background while playing audio I have in my AppDelegate this code snippet:
try session.setCategory(AVAudioSession.Category.playback,
mode: AVAudioSession.Mode.default,
options: [AVAudioSession.CategoryOptions.mixWithOthers, AVAudioSession.CategoryOptions.allowAirPlay])
try session.setActive(true)
This is how I initialise the Google Cast:
let criteria = GCKDiscoveryCriteria(applicationID: kReceiverAppID)
let options = GCKCastOptions(discoveryCriteria: criteria)
options.suspendSessionsWhenBackgrounded = false
GCKCastContext.setSharedInstanceWith(options)
GCKCastContext.setSharedInstanceWith(options)
If I add a dummy AVPlayer to my ViewController and play a random mp3 file on the player while I play other audio files overcast connection to the Google Cast session remains connected and the app works as expected until mp3 stops playing on AVPlayer.
Here is my AVPlayer snippet:
let videoURL = URL(string: "https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_5MG.mp3")
let player = AVPlayer(url: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
player.play()
Can anybody help me prevent the app from being suspended when it plays audio only while casting to TV?
Thanks!
I use AVPlayer to play a simple MP4 video. As I need to know when the video finishes, I add an observer for the notification AVPlayerItemDidPlayToEndTime.
This works fine, if the video is played on the device, but the notification is never posted if we are streaming the video from a device to an Apple TV (4th gen) with tvOS 12.2 via AirPlay.
Strangely, this problem only occurs with MP4 videos, not with HLS streams (m3u8), which makes me wonder if this might be a tvOS (or AirPlay) bug.
I created a small POC to isolate the problem, and this is what I do:
let bunny = "https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4"
// create a new player with every call to startVideo() for demo purposes
func startVideo() {
// remove layer of current play from playerContainer as
// a new one will be created below
if let sublayers = playerContainer.layer.sublayers {
for layer in sublayers {
layer.removeFromSuperlayer()
}
}
if let videoUrl = URL(string: bunny) {
// create player with sample video URL
self.player = AVPlayer(url: videoUrl)
guard let player = self.player else {return}
// add player layer to playerContainer
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = playerContainer.bounds
playerLayer.videoGravity = .resizeAspectFill
playerContainer.layer.addSublayer(playerLayer)
// add block-based observer to listen for AVPlayerItemDidPlayToEndTime event
let _ = NotificationCenter.default.addObserver(forName: NSNotification.Name.AVPlayerItemDidPlayToEndTime,
object: player.currentItem,
queue: .main) { notification in
print("Item did finish playing! \(notification)")
}
player.play()
}
}
Just to clarify again, this works fine, if one of the following conditions is true:
The video is played on the device, and no AirPlay is involved.
The video is streamed to an AppleTV 3rd gen.
An HLS instead of an MP4 video is used.
I also tried the following things, but the result was the same:
Don't set currentItem as object when adding observer.
Don't specify the queue when adding observer.
Don't use block-based but selector-based method to add an observer.
Any help is appreciated. This might be a duplicate of this question, but as there are no answers, and linked question is about HLS and not MP4, I decided to post this question anyway.
HI I'm developing Broadcast App for that I'm using Videocore library now how can i play that streaming video in ios app i tried with the MpMoviePlayer but it won't support the rtmp stream. so is there any third party libraries available for RTMP supported Players please help me
If you already have the RTMP live stream ready and playing as HLS then you can simply add .m3u8 after the stream name and make RTMP link to http. For example you have RTMP link like this:
rtmp://XY.Y.ZX.Z/hls/chid
You have to just make the url like this:
http://XY.Y.ZX.Z/hls/chid.m3u8
and it will play smoothly in iOS. I have tried following code and it is working fine.
func setPlayer()
{
// RTMP URL rtmp://XY.Y.ZX.Z/hls/chid be transcripted like this http://XY.Y.ZX.Z/hls/chid.m3u8 it will play normally.
let videoURL = URL(string: "http://XY.Y.ZX.Z/hls/chid.m3u8")
let playerItem = AVPlayerItem(url: videoURL!)
let adID = AVMetadataItem.identifier(forKey: "X-TITLE", keySpace: .hlsDateRange)
let metadataCollector = AVPlayerItemMetadataCollector(identifiers: [adID!.rawValue], classifyingLabels: nil)
//metadataCollector.setDelegate(self, queue: DispatchQueue.main)
playerItem.add(metadataCollector)
let player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
self.player = player
player.play()
}
But it will be slow and laggy because of the high resolution video stream upload. If you make the resolution to low when uploading the video stream, it will work smooth in low bandwidth network as well.
In my application I've to stream videos from server. For that I've used below Code
-(void)playingSong:(NSURL*) url{
AVAsset *asset = [AVAsset assetWithURL:url];
duration = asset.duration;
playerItem = [AVPlayerItem playerItemWithAsset:asset];
player = [AVPlayer playerWithPlayerItem:playerItem];
[player play];
}
All are Global Variables
It's playing all videos when network is good, but unable to play videos with big size, when network is slow.
Means It's not playing for big size videos and it's playing small videos;
I'm using http Server not https;
for ex : 3min video it's playing but for 1hr video it's not.
Why so?
Seems like you have to download the whole video before you can begin playback. It can also be because of your server not AVPlayer.
when you serve videos on a site using plain HTTP – known as
progressive download – the position of the header becomes very
important. Either the header is placed in the beginning of the file or
it’s places in the end of the file. In case of the latter, you’ll have
to download the whole thing before you can begin playback – because
without the header, the player can’t start decoding.
Have look at this guide if your problem is because of videos source.
Have a look at this thread and change you implementation accordingly.
Download video in local and then play in avplayer.
DispatchQueue.global(qos: .background).async {
do {
let data = try Data(contentsOf: url)
DispatchQueue.main.async {
// store "data" in document folder
let fileUrl = URL(fileURLWithPath: <#localVideoURL#>)
let asset = AVAsset(url: fileUrl)
let item = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: item)
let layer = AVPlayerLayer(player: player)
layer.bounds = self.view.bounds
self.view.layer.addSublayer(layer)
player.play()
}
} catch {
print(error.localizedDescription)
}
}
I'm trying to play a video of type avi in an application created in xcode written in swift.
The thing is all of the videos I have are in avi and I cannot afford time spent converting the videos right now. Is there a way to play the video in the provided Media player library?
the code I wrote plays the audio of the video only:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource(symbol, ofType:"avi")
let url = NSURL.fileURLWithPath(path!)
moviePlayer = MPMoviePlayerController(contentURL: url)
if let player = moviePlayer {
player.view.frame = self.view.bounds
player.prepareToPlay()
player.scalingMode = .AspectFill
self.view.addSubview(player.view)
}
or maybe there's a way to convert a video when the function is called?
I,
following the documentation of the MPMediaPlayer :
For movie files, this typically means files with the extensions .mov, .mp4, .mpv, and .3gp
So, unfortunately, you can't use the MPMediaPlayer to read your avi video.
Thanks to VLC for iOs source code, you can re-use it to implement a custom player to read these files.