how to show video in a small frame in ios - ios

I want to show a video of a topic in top half of the view and its matter in textview in the bottom half of the view. For that video control i want to have the features like play,pause,stop,ff etc. Also i want to play it from local resource as my web services hasn't been setup yet. pls suggest a good solution
I have tried UIWebView and added constraints to webview and textview but for some reason the web view is not showing the video correctly. below is my code
let purl = NSURL(fileURLWithPath: "/Users/Rohit/Desktop/videos/demo/demo/video1.mp4") webView.loadHTMLString("<iframe width = \" \(webView.frame.width) \" height = \"\(webView.frame.height)\" src = \"\(purl)\"></iframe>", baseURL: nil)
webView.backgroundColor = UIColor.green
webView.mediaPlaybackRequiresUserAction = true
webView.scrollView.isScrollEnabled = true
webView.isUserInteractionEnabled = true

Import AVFoundation and AVKit
Then play the video using an URL object (in Swift 3 NSURL is renamed to URL)
let player = AVPlayer(URL: URI)
let controller = AVPlayerViewController()
controller.player = player
self.addChildViewController(controller)
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 10, width: screenSize.width, height: (screenSize.height - 10) * 0.5)
controller.view.frame = videoFrame
self.view.addSubview(controller.view)
player.play()

You can use AVPlayerLayer and give it bounds.
private func inits() {
//let rootLayer: CALayer = self.layer
// rootLayer.masksToBounds = true
avPlayerLayer = AVPlayerLayer(player: player)
avPlayerLayer.bounds = self.bounds
// avPlayerLayer.backgroundColor = UIColor.yellowColor().CGColor
self.layer.insertSublayer(avPlayerLayer, atIndex: 0)
}

Related

AVPlayer Aspect Ratio

Ok so in my iOS app there is a screen with an AVPlayerViewController that takes care of playing videos. When this video is played it fills the entire screen however on some videos they video seems stretched as if it is being forced to fit. Is there any way to make the video fit the entire screen without losing the aspect ratio.
The code below is what I use to lay out the AVPlayerController. I figured some error here is the cause of this flaw in aspect ratio.
/
// Setup the view for stories
private func setupViews() {
view.backgroundColor = .clear
// Setup the blur view for loading
blurView = UIVisualEffectView(frame: view.frame)
blurView.effect = UIBlurEffect(style: .regular)
self.view.addSubview(blurView)
// Indicator for loading
let indicatorFrame = CGRect(x: view.center.x - 20, y: view.center.y - 20, width: 40, height: 40)
indicator = UIActivityIndicatorView(frame: indicatorFrame)
indicator.hidesWhenStopped = true
indicator.activityIndicatorViewStyle = .whiteLarge
blurView.contentView.addSubview(indicator)
// Setup the Progress bar
// spb = SegmentedProgressBar(numberOfSegments: allStories.count)
//// spb.frame = CGRect(x: 0, y: 1, width: self.view.frame.width, height: 9)
// self.view.addSubview(spb)
// spb.snp.makeConstraints { (make) in
// make.left.right.equalTo(view.safeAreaLayoutGuide)
// make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(1)
// make.height.equalTo(9)
// }
//
// spb.delegate = self
// Player Controller
playerController = AVPlayerViewController()
playerController.showsPlaybackControls = false
self.addChildViewController(playerController)
// Image view for the story
imageView = UIImageView(frame: self.view.frame)
infoView = UIView(frame: self.view.frame)
infoView.backgroundColor = UIColor.clear
// The image view for the user of the current story
infoImageView = UIImageView()
self.view.addSubview(imageView)
self.view.addSubview(playerController.view)
// self.view.bringSubview(toFront: spb)
self.view.addSubview(infoView)
self.infoView.addSubview(infoImageView)
infoImageView.snp.makeConstraints { (make) in
make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(2)
make.left.equalTo(view.safeAreaLayoutGuide.snp.left).offset(10)
make.height.width.equalTo(30)
}
infoImageView.layer.cornerRadius = 15
infoImageView.layer.masksToBounds = true
// The name for the user of the current story
infoNameLabel = UILabel()
infoNameLabel.backgroundColor = UIColor.black.withAlphaComponent(0.1)
infoNameLabel.textColor = UIColor.white
infoNameLabel.font = UIFont.boldSystemFont(ofSize: 18)
infoNameLabel.adjustsFontSizeToFitWidth = true
self.infoView.addSubview(infoNameLabel)
infoNameLabel.snp.makeConstraints { (make) in
make.left.equalTo(infoImageView.snp.right).offset(5)
make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(2)
make.height.equalTo(30)
make.width.equalTo(80)
}
// Time label for long ago the story was posted
infoTimeLabel = UILabel()
infoTimeLabel.backgroundColor = UIColor.black.withAlphaComponent(0.1)
infoTimeLabel.textColor = UIColor.white
self.infoView.addSubview(infoTimeLabel)
infoTimeLabel.snp.makeConstraints { (make) in
make.left.equalTo(infoNameLabel.snp.right).offset(5)
make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(2)
make.height.equalTo(30)
make.width.equalTo(50)
}
infoView.isUserInteractionEnabled = true
infoView.addGestureRecognizer(tapInfoView)
infoView.addGestureRecognizer(swipeInfoView)
infoTimeLabel.layer.cornerRadius = 10
infoTimeLabel.layer.masksToBounds = true
infoTimeLabel.textAlignment = .center
infoNameLabel.layer.cornerRadius = 10
infoNameLabel.layer.masksToBounds = true
infoNameLabel.textAlignment = .center
playerController.videoGravity = AVLayerVideoGravity.resizeAspectFill.rawValue
playerController.view.frame = view.frame
// spb.durations = durations
}
Any help is greatly appreciated
to keep the video aspect ratio in the defined view frame use
AVLayerVideoGravity.resizeAspect.
For the current case replace
playerController.videoGravity = AVLayerVideoGravity.resizeAspectFill.rawValue
to
playerController.videoGravity = AVLayerVideoGravity.resizeAspect
I am not sure about it but use this :
playerController.view.frame = view.bounds
Instead of this:
playerController.view.frame = view.frame
The AVLayerVideoGravity.resizeAspectFill.rawValue should do what is says and I never had a problem with it. However, I use the bounds instead of the frame and I remember getting problem when using the frame.
You also have AVLayerVideoGravity.resizeAspect.rawValue that will fit the video instead of filling it.
You can also try setting the frame before the video gravity.

AVPlayerViewController controls not working

I have an app which plays video clips on demand. This has worked well in previous versions of Xcode but I've upgraded to 8.3.3 and am having problems with the AVPlayerViewController.
The video plays and displays correctly. The control bar appears at the bottom of the view but does not respond to taps and, once faded out, does not reappear on tapping the video - unless, that is, I tap near the top left of the view.
My guess is that the actual controls are hidden in some kind of overlay which has the wrong size i.e. it does not properly overlay the whole of the video view. Is there some way to force the AVPlayerViewController to relayout?
I've tried adding:
_playerController!.view.setNeedsLayout()
_playerController!.view.layoutIfNeeded()
But this has no effect.
Here's my code:
override func viewDidLoad() {
super.viewDidLoad()
_player = AVPlayer()
_playerController = AVPlayerViewController()
_playerController!.showsPlaybackControls = true
_playerController!.allowsPictureInPicturePlayback = false
_playerController!.videoGravity = AVLayerVideoGravityResizeAspectFill
_playerController!.player = _player
self.addChildViewController(_playerController!)
videoView.addSubview(_playerController!.view)
...
override func viewDidLayoutSubviews() {
let frame = UIScreen.main.bounds
_vidWidth = frame.width - 256.0
_vidHeight = _vidWidth / 854.0 * 480.0
videoView.frame = CGRect(x: 0, y: 10.0, width: _vidWidth, height: _vidHeight)
videoView.backgroundColor = UIColor.black
_playerController?.view.frame = CGRect(x: 0, y: 0, width: _vidWidth, height: _vidHeight)
...
func playVideo(_ clip: Clip) {
var videoUrl: URL? = nil
if clip.offlineLocation != nil && clip.state == 2 {
_videoPath = clip.offlineLocation!
videoUrl = URL(fileURLWithPath: _videoPath!)
}
else {
_videoPath = "https://xxxx.cloudfront.net/" + clip.location
videoUrl = URL(string: _videoPath!)
}
NSLog(_videoPath!)
let asset = AVURLAsset(url:videoUrl!, options:nil)
let playerItem = AVPlayerItem(asset: asset)
_player!.replaceCurrentItem(with: playerItem)
_player!.play()
}

Add AVPlayer subview to UIView

I am using the following code to create a vertical scrollview with paging enabled which works perfectly fine. Now I would like to add a subview of the type AVPlayer (?) to homeView, view2, view3. I can put setupCustomPlayer() in the initiateScrollView() function which works very well, too. However, it is not attached to any of the previously-mentioned views. If I try to add a subview using the function addSubview(anything) it tells me a UIView is expected. I need the UIViews as the vertical sliding feed is very important. Does someone know how to add it as a subview? The video is going to cover the entire screen and going to serve as kind of a background video one could say (if you would like to know)
Code:
func setupCustomPlayer() {
print("check")
AVPlayerVC.view.frame = self.view.frame
AVPlayerVC.view.sizeToFit()
AVPlayerVC.showsPlaybackControls = false
self.view.addSubview(AVPlayerVC.view)
let videoURL = NSURL(string: "http://URL")
let player = AVPlayer(url: videoURL! as URL)
AVPlayerVC.player = player
AVPlayerVC.player?.play()
}
func initiateScrollView() {
//create scrollView with paging enabled
let scrollView = UIScrollView(frame: view.bounds)
scrollView.isPagingEnabled = true
view.addSubview(scrollView)
//do not show vertical scroll indicator
scrollView.showsVerticalScrollIndicator = false;
//get page size
let pageSize = view.bounds.size
//individual views
let homeView = UIView()
homeView.backgroundColor = .green
let view2 = UIView()
view2.backgroundColor = .blue
let view3 = UIView()
view3.backgroundColor = .red
//array with individual views
let pagesViews = [homeView, view2, view3]
//amount of views
let numberOfPages = pagesViews.count
//add subviews (pages)
for (pageIndex, page) in pagesViews.enumerated(){
page.frame = CGRect(origin: CGPoint(x:0 , y:CGFloat(pageIndex) * pageSize.height), size: pageSize)
scrollView.addSubview(page)
}
//define size of scrollView
scrollView.contentSize = CGSize(width: pageSize.width, height: pageSize.height * CGFloat(numberOfPages))
}
Could you try this?
func setupCustomPlayer() {
print("check")
let player = AVPlayer(url: yourFileUrl)
var playerLayer: AVPlayerLayer?
playerLayer = AVPlayerLayer(player: player)
playerLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
playerLayer!.frame = self.view.frame
self.view.layer.addSublayer(playerLayer!)
player.play()
}

AVPlayerLayer Position in UIView Layer

I am writing an application using Swift to view surveillance cameras via HLS. I have the basic device list working and I am able to segue to the Live view and display the stream however, I need to move the AVPlayerLayer and I am having trouble figuring this out. Here is my current code:
let player = AVPlayer(URL: url!)
let playerLayer = AVPlayerLayer(player: player)
let view = UIView(frame: CGRectMake(0, 0, screenSize.width, screenSize.height))
self.view.layer.borderWidth = 1
self.view.layer.borderColor = UIColor(red:222/255.0, green:225/255.0, blue:227/255.0, alpha: 1.0).CGColor
self.view.layer.addSublayer(playerLayer)
playerLayer.frame = view.bounds
player.play()
I want the AVPlayerLayer to be placed 50 points below the top because I have a header for each view scene.
Thank you!
So it just so happens that you cannot place a sub layer in a view in a specific position. Here is the solution:
let player = AVPlayer(URL: url!)
let playerController = AVPlayerViewController()
playerController.player = player
playerController.view.frame = CGRectMake(0, 50, screenSize.width, 240)
self.view.addSubview(playerController.view)
self.addChildViewController(playerController)
player.play()
I had to set a specific height of the player and then the position.
I don't see where you associate the PlayerLayer with a View and/or add it as a subview/layer to anything? You will need to add it as a sublayer.
let player = AVPlayer(URL: url!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = CGRectMake(0,50,screenSize.width, screenSize.height)
self.view.layer.addSublayer(playerLayer)
player.play()
I moved the Y position by 50 as you suggested you wanted to do in your question.

AVPlayer too big for screen

I'm trying to play a video in a scrollView. For that matter, I ended up using an AVPlayerViewController because it worked really well with the spacing between multiple videos. The problem is however, that all the videos are approx. 1/3 bigger than the size of the screen. What did I do wrong?
let player = AVPlayer(URL: NSURL(string: videoLink))
let playerController = AVPlayerViewController()
playerController.player = player
playerController.showsPlaybackControls = false
playerController.videoGravity = AVLayerVideoGravityResizeAspect
playerController.view.frame = CGRectMake(0, (UIScreen.mainScreen().bounds.height) * CGFloat(index), UIScreen.mainScreen().bounds.width,0)
UPDATE:
The following code still shows the video. The frame is really small, but still shows. I tried debugging it by printing out its "view.frame.bounds.width", "view.frame.bounds.size.width", "view.frame.size.width", and "view.frame.width" and they all said "0"
playerController.view.frame = CGRectMake(0, (self.view.frame.size.height - 64) * CGFloat(index) + 30, 0, 0)

Resources