Add custom controls to AVPlayer in swift
here I add the points , you need to customize based on your need.
Step-1
initially hide your AVPlayer
controls,
YourAVPlayerViewController.showsPlaybackControls = false
Step-2
create the structure like
one label for current Duration, One label for overall Duration, one UIbutton for pause and play your current player and one UISlider for seek The video.
step-3
initially close the simple steps.
first stop and play the player using button action , currentPlayer is your AVPlayer name.
@IBAction func handlePlayPauseButtonPressed(_ sender: UIButton) {
// sender.isSelected ? currentPlayer.pause() : currentPlayer.play()
if sender.isSelected {
currentPlayer.pause()
}
else {
currentPlayer.play()
}
}
second set the video duration, as like
let duration : CMTime = currentPlayer.currentItem!.asset.duration
let seconds : Float64 = CMTimeGetSeconds(duration)
lblOverallDuration.text = self.stringFromTimeInterval(interval: seconds)
third set the player current time to current duration label
let duration : CMTime = currentPlayer.currentTime()
let seconds : Float64 = CMTimeGetSeconds(duration)
lblcurrentText.text = self.stringFromTimeInterval(interval: seconds)
the following method is convert from NSTimeinterval to HH:MM:SS
func stringFromTimeInterval(interval: TimeInterval) -> String {
let interval = Int(interval)
let seconds = interval % 60
let minutes = (interval / 60) % 60
let hours = (interval / 3600)
return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
}
finally we go for slider control for calulate the seek time
_playheadSlider.addTarget(self, action: #selector(self.handlePlayheadSliderTouchBegin), for: .touchDown)
_playheadSlider.addTarget(self, action: #selector(self.handlePlayheadSliderTouchEnd), for: .touchUpInside)
_playheadSlider.addTarget(self, action: #selector(self.handlePlayheadSliderTouchEnd), for: .touchUpOutside)
_playheadSlider.addTarget(self, action: #selector(self.handlePlayheadSliderValueChanged), for: .valueChanged)
lets we go for action, initially when touchbegin is start then stop the player
handlePlayheadSliderTouchBegin
@IBAction func handlePlayheadSliderTouchBegin(_ sender: UISlider) {
currentPlayer.pause()
}
set the current item label for calculate the
sender.value * CMTimeGetSeconds(currentPlayer.currentItem.duration)
@IBAction func handlePlayheadSliderValueChanged(_ sender: UISlider) {
let duration : CMTime = currentPlayer.currentItem!.asset.duration
let seconds : Float64 = CMTimeGetSeconds(duration) * sender.value
// var newCurrentTime: TimeInterval = sender.value * CMTimeGetSeconds(currentPlayer.currentItem.duration)
lblcurrentText.text = self.stringFromTimeInterval(interval: seconds)
}
finally move the player based on seek
@IBAction func handlePlayheadSliderTouchEnd(_ sender: UISlider) {
let duration : CMTime = currentPlayer.currentItem!.asset.duration
var newCurrentTime: TimeInterval = sender.value * CMTimeGetSeconds(duration)
var seekToTime: CMTime = CMTimeMakeWithSeconds(newCurrentTime, 600)
currentPlayer.seek(toTime: seekToTime)
}
iOS - Adding controls on top of AVPlayerViewController
I solved the issue by adding the following two lines alongside the addSubview function:
self.addChildViewController(playerViewController)
playerView.addSubview(playerViewController.view)
playerViewController.didMove(toParentViewController: self)
Custom control for playback speed for AVPlayerViewController
- Can we add custom playback speed (0.5, 1.0, 1.5, 2.0) control to
AVPlayerViewController
?
You can add a custom playback speed button to AVPlayerViewController
by doing a little hack.
In iOS 11, i.e., you can add a button to the AVPlayerViewController
by adding the control next to the "Play/Pause" button. That button has an Accessible Identifier which will help you find that control.
So, what I did was basically find that "Play/Pause" button and add my Playback Speed button to the superview of the "Play/Pause" button.
func findPlayPauseButton(view: UIView) -> UIView? {
if view.accessibilityIdentifier == "Play/Pause" {
return view
}
for subview in view.subviews {
if let result = findPlayPauseButton(view: subview) {
return result
}
}
return nil
}
guard let playerView = playerViewController?.view else {
return
}
guard let playPauseButton = findPlayPauseButton(view: playerView) else {
return
}
if let playerControlsView = playPauseButton.superview {
let playbackSpeedButton = UIButton(type: .system)
playbackSpeedButton.accessibilityIdentifier = "PlaybackSpeed"
playbackSpeedButton.setTitle("1 X", for: .normal)
playbackSpeedButton.addTarget(self, action: #selector(self.playbackSpeedButtonTapped), for: .touchUpInside)
playbackSpeedButton.translatesAutoresizingMaskIntoConstraints = false
playerControlsView.addSubview(playbackSpeedButton)
NSLayoutConstraint.activate([
playbackSpeedButton.heightAnchor.constraint(equalTo: playPauseButton.heightAnchor),
playbackSpeedButton.widthAnchor.constraint(equalToConstant: 50),
playbackSpeedButton.leadingAnchor.constraint(equalTo: playPauseButton.trailingAnchor, constant: 70),
playbackSpeedButton.bottomAnchor.constraint(equalTo: playPauseButton.bottomAnchor),
])
}
Result:
As you may know, this has a lot of downsides because of all the edge cases that you will find, i.e., you need to take care the landscape as well, you need to check if the hack is still valid on every new iOS version, etc. If you app supports iOS 10, then things are different because the UI of the AVPlayerViewController
has changed in iOS 11.
- Is there a way we can refresh speed rate using an UISlider value change?
Yes, instead of a UIButton
for changing the playback speed, just add an UISlider
.
- Can we change the playback speed if it is playing currently?
Yes, if it's playing then you just need to change the rate
property of the player: for example to 1.25 X => playerViewController.player?.rate = 1.25
.
UPDATE:
Enhancement requested! Radar number is 46022646: Playback speed control for AVPlayerViewController (Video).
Can AVPlayerViewController be customized via Storyboard or must it be done via adding subviews?
The short answer as of now, it is not possible to work and customize AVPlayerViewController
in your storyboard.
You probably added a UIViewController
in your storyboard and set the class of the UIViewController
to AVPlayerViewController
and probably the AVPlayerViewController
's implementation is not prepared to handle this.
For now, you cannot add an AVPlayerViewController
to the storyboard and move the controls around or add your subviews.
The closest thing you can do to working with a view in storyboard is to subclass AVPlayerViewController
class CustomAVPlayerController: AVPlayerViewController
{
// your implementation
}
And you can work with this in your storyboard provided you implement required init?(coder: NSCoder)
However, tread this path with caution as Apple recommends against subclassing AVPlayerViewController
.
Overview
A player view controller makes it simple to add media
playback capabilities to your app that match the styling and features
of the native system players. Using this object also means that your
app automatically adopts the new features and styling of future
operating system releases.
I would say use this only if you have to do some basic work like detecting orientation changes, add some colors to views etc and not to mess around with subviews and controls.
If you only work with MP3s you can get away with playing your audio using an AVPlayer
in a normal UIViewController
rather AVPlayerViewController
and this is what I did for one of the apps I developed - Reliable Radio
Here is an example of a UI I was able to achieve:
The pro of the above approach is that you can customize the view as you like, the con of that approach is you have to develop all the controls like play, forward, rewind, volume, scrubber etc
Here is an idea on how to achieve that
So it's a choice on what you are willing to compromise:
- Not much UI customization but all the controls for free - AVPlayerViewController
- Full UI control but develop your own controls - AVPlayer contained in a custom UIViewController
I will also answer your second question shortly about the UITextView scroll issue with a solution that is somewhere halfway between 1 and 2 above
MPMoviewcontroller and AVPlayer with custom control
I have the same issue with MPMoviePlayerController. Also We can't add more than one MPMoviePlayerController in a same view. For this, I have created a custom player using AVPlayer having basic features. You can download it from my github account HRVideoPlayer. Let me know if you want more detailed version. I have built my own video player having all functionalities like Seeking, volume control, brightness control, replace currentItem, Repeat and shuffle.
AVPlayer with playback controls of avplayerviewcontroller
No. The usual solution (explicitly advised by Apple) is to use the AVPlayerViewController as an embedded view controller - i.e., make your view controller a custom parent view controller and the AVPlayerViewController its child, and now you can place its view (the movie and the controls) inside your view as a subview in good order. Example (self
is your view controller):
let url = // whatever
let player = AVPlayer(URL:url)
let avPlayerViewController = AVPlayerViewController()
avPlayerViewController.player = player
avPlayerViewController.view.frame = // whatever
self.addChild(avPlayerViewController)
self.view.addSubview(avPlayerViewController.view)
avPlayerViewController.didMove(toParent: self)
Related Topics
Is There an iPhone Se Simulator for Xcode 11, iOS 13
-Canopenurl: Failed for Url: "Fbauth2:/" (Osstatus Error -10814.)"
Firebase Cloud Messaging - Send Message to All Users
Passing Parameters to a Method Called by Nstimer in Swift
Can Not Save File Inside Tmp Directory
Use Didselectrowatindexpath or Prepareforsegue Method for Uitableview
Native Facebook App Does Not Open with Facebook Login in iOS 9
Change Color of Back Button in Navigation Bar
Analysing Assets.Car File in iOS
Why Is Uicollectionviewcell's Outlet Nil
Cocoapods: Failed to Connect to Github to Update the Cocoapods/Specs Specs Repo
How to Check If a File Exists in Documents Folder
What Exactly Can Corebluetooth Applications Do Whilst in the Background
Detecting iPhone 6/6+ Screen Sizes in Point Values
Xcode 6 - How to Pick Signing Certificate/Provisioning Profile for Ad-Hoc Distribution
How to Force Wkwebview to Ignore Hardware Silent Switch on iOS