Having my UIView go from one video to the next - ios

I'm kinda new at this, Ive successfully embedded a video into a UIView. Got it to play automatically, without any controls. So far so good.
Now I want to be able to play the next video, and ideally the user can swipe and the next video will start playing... here's the code I have now;
#IBOutlet weak var videoView: UIView!
var player: AVPlayer!
var avpController = AVPlayerViewController()
override func viewDidLoad() {
super.viewDidLoad()
let filepath: String? = Bundle.main.path(forResource: "jordanreel", ofType: "mp4")
let fileURL = URL.init(fileURLWithPath: filepath!)
player = AVPlayer(url: fileURL)
avpController.player = player
avpController.view.frame.size.height = videoView.frame.size.height
avpController.view.frame.size.width = videoView.frame.size.width
avpController.showsPlaybackControls = false
avpController.player?.play()
self.videoView.addSubview(avpController.view) }
}

Related

Reality Composer - How to add a video on to an usdz object?

I am trying to add a video onto the usdz object. The code which i am trying with is as below
class ViewController: UIViewController {
#IBOutlet var arView: ARView!
let panelName = "plane.usdz"
var playerLooper: AVPlayerLooper!
override func viewDidLoad() {
super.viewDidLoad()
let url = Bundle.main.url(forResource: "video1", withExtension: "mp4")
let playerItem = AVPlayerItem(url: url!)
let player = AVQueuePlayer()
playerLooper = AVPlayerLooper(player: player, templateItem: playerItem)
let material = VideoMaterial(avPlayer: player)
let anchor = AnchorEntity(world: [0,0,-2])
do {
let entity = try Entity.loadModel(named: panelName)
entity.model?.materials = [material]
anchor.addChild(entity)
arView.scene.anchors.append(contentsOf: [anchor])
} catch {
assertionFailure("Could not load the panel asset.")
}
player.play()
let config = ARWorldTrackingConfiguration()
arView.session.run(config)
}
}
Here i have created a usdz object "plane.usdz" on which i am trying to add a video "video1.mp4". I am able to add the video, but its playing in an inverted manner. How can i make it play properly?

AVPlayerLayer says always nil

I don't understand why it is not working. I pass a videoURL trough a segue to a another ViewController. This works fine.
In the other ViewController I want to play the video. But for some reason it is not working.
I unwrap the URL with optional binding. But playerLayer does not accept the URL. It says always nil.
This is the URL: VideoURL Optional(file:///var/mobile/Containers/Data/Application/517BA864-F5CB-4E2C-BE54-D42555569266/Documents/3d.mov)
My code:
var player: AVPlayer?
var playerLayer: AVPlayerLayer?
var videoURL: URL?
func playVideo() {
if let _videoURL = videoURL {
player = AVPlayer(url: _videoURL)
playerLayer = AVPlayerLayer(layer: player!)
playerLayer?.frame = contentView.layer.bounds
playerLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
self.contentView.layer.addSublayer(playerLayer!)
player?.play()
}
Try creating an AVURLAsset and an AVPlayerItem. Then pass that AVPlayerItem into the AVPlayer rather than trying to use the URL init.
I tested this with a sample video I downloaded from here. Note there is no sound in this video.
import UIKit
import AVFoundation
class ViewController: UIViewController {
private let videoUrl = Bundle.main.url(forResource: "file_example_MOV_1920_2_2MB", withExtension: "mov")!
private var videoPlayer: AVPlayer?
private var playerLayer: AVPlayerLayer?
override func viewDidLoad() {
super.viewDidLoad()
playVideo()
}
func playVideo() {
let asset = AVURLAsset(url: videoUrl)
let primaryPlayerItem = AVPlayerItem(asset: asset)
let player = AVPlayer(playerItem: primaryPlayerItem)
let videoLayer = AVPlayerLayer(player: player)
videoLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoLayer.frame = view.bounds
view.layer.addSublayer(videoLayer)
videoPlayer = player
playerLayer = videoLayer
videoPlayer?.play()
}
}
Try the below code. It's working.
var player: AVPlayer!
var playerLayer: AVPlayerLayer!
func playVideo() {
if let url = videoURL {
do {
let item:AVPlayerItem = AVPlayerItem(url: url)
player = AVPlayer(playerItem: item)
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = contentView.bounds
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
self.contentView.layer.addSublayer(playerLayer)
player.play()
} catch {
print("Error1", error.localizedDescription)
}
}
}

Problem with deallocation of AVPlayer/AVPlayerItem

I implemented a code to check if AVPlayer deallocates. Unfortunately it does not. Do I miss something?
func testPlayerDealloc() {
var player: AVPlayer? = AVPlayer()
weak var weakPlayer = player
weak var weakPlayerItem: AVPlayerItem?
let urlString = "http://csm-e.cds1.yospace.com/csm/extlive/yospace02,hlssample.m3u8"
if let player = player, let url = URL(string: urlString) {
let playerItem = AVPlayerItem(url: url)
weakPlayerItem = playerItem
player.replaceCurrentItem(with: playerItem)
}
player?.replaceCurrentItem(with: nil)
player = nil
XCTAssertNil(weakPlayer)
XCTAssertNil(weakPlayerItem)
}
At the end both, the weakPlayer and the weakPlayerItem are not nil.

Create VideoPlayer With Custom Size in Swift 3

i want to show .mov file in custom size. i have an xib file for my controller.
thats top view is subclass of UIView. i want to show video in this view.
there is my code for create video view. but there is problem in size of my video player. how can solve this problem.
there is my code :
private func playVideo() {
guard let path = Bundle.main.path(forResource: "video_2017-06-30_15-49-05", ofType:"mov") else {
debugPrint("video.m4v not found")
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.player = player
let avPlayerLayer = AVPlayerLayer(player: player)
avPlayerLayer.frame = videoView.layer.frame
videoView.layer.insertSublayer(avPlayerLayer, at: 0)
}
If you want a native player to be added to your view with the seek bar and play pause button then use following code:
private func playVideo() {
guard let path = Bundle.main.path(forResource: "SampleVideo", ofType:"mp4") else {
debugPrint("video.m4v not found")
return
}
let player = AVPlayer(url: URL(fileURLWithPath: path))
let playerController = AVPlayerViewController()
playerController.player = player
playerController.view.frame = videoView.bounds
videoView.addSubview(playerController.view)
player.play()
}
and if you want just the video to be played in your view with AVPlayerLayer then you can do something like below:
var player : AVPlayer!
var avPlayerLayer : AVPlayerLayer!
#IBOutlet weak var videoView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
guard let path = Bundle.main.path(forResource: "SampleVideo", ofType:"mp4") else {
debugPrint("video.m4v not found")
return
}
player = AVPlayer(url: URL(fileURLWithPath: path))
avPlayerLayer = AVPlayerLayer(player: player)
avPlayerLayer.videoGravity = AVLayerVideoGravity.resize
videoView.layer.addSublayer(avPlayerLayer)
playVideo()
}
override func viewDidLayoutSubviews() {
avPlayerLayer.frame = videoView.layer.bounds
}
private func playVideo() {
player.play()
}
This worked perfect for me hope it works for you :)

MPMoviePlayerController shows only black screen - Swift

I have a View inside a ViewController that I want to add a move player controller to it. But so far I'm only getting a black screen.
I'm running this on the simulator, and using the apple dev stream which I tested in Safari and it works.
The videoView is added to the controller through an IBOutlet. I'm using Xcode 6 beta 7.
This is all inside a UIViewController.
Declaration of videoView 320x320 (global):
#IBOutlet var videoView: UIView!
Declaration of MPMoviePlayerController (global):
var videoPlayer : MPMoviePlayerController = MPMoviePlayerController()
Adding videoPlayer to View:
videoURLWithPath = "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"
let videoURL = NSURL(fileURLWithPath: videoURLWithPath)
videoPlayer.movieSourceType = MPMovieSourceType.Streaming;
videoPlayer.contentURL = videoURL
videoPlayer.view.frame = videoView.bounds
videoView.addSubview(videoPlayer.view)
videoPlayer.controlStyle = MPMovieControlStyle.Embedded
videoPlayer.prepareToPlay()
videoPlayer.play()
Storyboard:
Simulator:
Update:
I've also tried doing this. Super simple. And I'm still getting the same result. The frame size is set that way so that I can see that the player has actually been added.
let streamURL = NSURL(string: "http://www.thumbafon.com/code_examples/video/segment_example/prog_index.m3u8")
var streamPlayer = MPMoviePlayerController(contentURL: streamURL)
streamPlayer.view.frame = CGRect(x: 10, y: 10, width: 200, height: 200)
streamPlayer.controlStyle = MPMovieControlStyle.Embedded
videoView.addSubview(streamPlayer.view)
streamPlayer.play()
I ended up ditching MPMoviePlayerController and opted to use AVFoundation instead.
Working example:
Global declarations:
var player : AVPlayer? = nil
var playerLayer : AVPlayerLayer? = nil
var asset : AVAsset? = nil
var playerItem: AVPlayerItem? = nil
inside viewDidLoad:
let videoURLWithPath = "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"
let videoURL = NSURL(string: videoURLWithPath)
asset = AVAsset.assetWithURL(videoURL) as? AVAsset
playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: self.playerItem)
playerLayer = AVPlayerLayer(player: self.player)
playerLayer!.frame = videoView.frame
videoView.layer.addSublayer(self.playerLayer)
player!.play()
Rather than using MPMoviePlayerController, this works perfectly for me:
// import MediaPlayer
var moviePlayer : MPMoviePlayerViewController?
#IBAction func playVideo() {
let path = NSBundle.mainBundle().pathForResource("ra3", ofType:"mp4")
let url = NSURL.fileURLWithPath(path!)
let videoURL = url
moviePlayer = MPMoviePlayerViewController(contentURL: videoURL )
if let player = moviePlayer {
player.view.frame = self.view.bounds
self.presentViewController(moviePlayer!, animated: true, completion: nil)
}
else {
NSLog("no player")
}
}

Resources