MP4 video as background - ios

I am trying to create something like vine app has.
This is what I got so far:
func playVideo() {
let path = NSBundle.mainBundle().pathForResource("WelcomeVideo", ofType: "mp4")
let pathURL = NSURL.fileURLWithPath(path!)
let myPlayer = MPMoviePlayerViewController(contentURL: pathURL)
myPlayer.moviePlayer.repeatMode = .One
presentMoviePlayerViewControllerAnimated(myPlayer)
}
But the problem is that it shows the playbutton and such.. Any suggestions?

Have you tried with something like this ?
myPlayer.moviePlayer.controlStyle = MPMovieControlStyleNone

Related

AVPlayer Inside A UIView

So I have a view on my HomeViewController that I want to play a video inside of. on viewDidLoad() I am calling playVideo() here is my code:
func playVideo() {
guard let filePath = Bundle.main.path(forResource: "video", ofType: "mov") else {
debugPrint("video.mov not found.")
return
}
let avPlayer = AVPlayer(url: URL(fileURLWithPath: filePath))
let avPlayerController = AVPlayerViewController()
avPlayerController.player = avPlayer
avPlayerController.view.frame = playerView.bounds
avPlayerController.showsPlaybackControls = false
avPlayerController.player?.play()
playerView.addSubview(avPlayerController.view)
playerView.bringSubview(toFront: QRButton)
}
All I get is a black background and no video. What am I doing wrong? I have tried to solve this for a while now.
iOS: 11.2 beta
Xcode: 9.2 beta
Try to use avPlayer as a class variable, maybe it has been released before it can start to play.
class ViewController: UIViewController {
var avPlayer:AVPlayer?
func playVideo() {
guard let filePath = Bundle.main.path(forResource: "video", ofType: "mov") else {
debugPrint("video.mov not found.")
return
}
avPlayer? = AVPlayer(url: URL(fileURLWithPath: filePath))
let avPlayerController = AVPlayerViewController()
avPlayerController.player = avPlayer
avPlayerController.view.frame = playerView.bounds
avPlayerController.showsPlaybackControls = false
avPlayerController.player?.play()
playerView.addSubview(avPlayerController.view)
playerView.bringSubview(toFront: QRButton)
}
}

swift - How to make Add to Favorites with NSURL array

I'm trying to build an app stores specific sounds which user can play. I assure you I've searched for 2 days but I couldn't what I look for. (Or I couldn't successful with those tuts idk)
The app stores sounds like this:
var sound1 = NSURL(fileURLWithPath: Bundle.main.path(forResource: "Adios Amigos", ofType: "mp3")!)
var sound2 = NSURL(fileURLWithPath: Bundle.main.path(forResource: "ses2", ofType: "mp3")!)
var sound3 = NSURL(fileURLWithPath: Bundle.main.path(forResource: "ses3", ofType: "mp3")!)
var sound4 = NSURL(fileURLWithPath: Bundle.main.path(forResource: "ses4", ofType: "mp3")!)
var soundArray: [NSURL] = [sound1, sound2, sound3, sound4]
here is my button that play sounds as random:
#IBAction func Rastgele(sender: Any) {
let randNo = Int(arc4random_uniform(UInt32(soundArray.count))) // 0...ArrayCount
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
try audioPlayer = AVAudioPlayer(contentsOf: (soundArray[randNo] as NSURL) as URL)
audioPlayer.prepareToPlay()
audioPlayer.play()
self.sesLabel.text = soundArray[randNo].deletingPathExtension?.lastPathComponent
soundIndex = randNo} catch {
print(error)
}
}
and here is my IBAction button that I couldn't fill inside with code.
#IBAction func Favori(_ sender: Any) {
// empty
}
I tried to use NSUserdefaults but I couldn't achieve what I want.
I also tried to pull the array item from my array to insert another array but I faced many problems with because of type of array(NSURL)
So, 'Favori' button should store as Favorites then I can show favorited sounds in other table view.
Thanks in advance.
EDIT
I found a solution using Core Data and converting NSURLs to URL. Thanks to the #rmaddy for helpful comment. The working code is down below;
#IBAction func Favori(_ sender: Any) {
// save core data
let app = UIApplication.shared.delegate as! AppDelegate
let context = app.persistentContainer.viewContext
let newSound = NSEntityDescription.entity(forEntityName: "Sounds", in: context)
let sound = NSManagedObject(entity: newSound!, insertInto: context)
sound.setValue(soundArray[soundIndex].deletingPathExtension().lastPathComponent, forKey: "soundName")
do { try context.save()
soundItems.append(sound)
print(sound)
}
catch
{
print("error")
}
}
When you click on the button, save the URL into core data or a local data base using sqlite or a server.
If you just want to pass it to another tableview without saving it (data will lost when you kill the app), you can pass that around using a delegate or notification center.

Seamless looping Video using AVPlayer- Swift

I am using AVPlayer to play local video in background using loop and video is playing fine but after finishing video it takes pause to play video in loop. I have tried many methods and also seen many post on stack overflow but i failed to find appropriate solution. I am using Swift3.
Code is here :
var videoplayer :AVPlayer = AVPlayer()
override func viewDidLoad() {
super.viewDidLoad()
let path = Bundle.main.path(forResource: "background4", ofType: "mp4")
videoplayer = AVPlayer(url: URL(fileURLWithPath: path!))
videoplayer.volume = 0
videoplayer.actionAtItemEnd = AVPlayerActionAtItemEnd.none;
let playerLayer = AVPlayerLayer(player: videoplayer)
playerLayer.frame = self.view.frame
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
if (videoplayer.rate != 0) {
print("playing videoplayer")
self.blurBgImage.isHidden = true
}
playerLayer.zPosition = -1
videoplayer.rate = 0
videoplayer.play()
self.blurBgImage.layer.addSublayer(playerLayer)
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: videoplayer.currentItem, queue: nil, using: { (_) in
DispatchQueue.main.async {
let t1 = CMTimeMake(5, 100)
self.videoplayer.seek(to: t1)
self.videoplayer.play()
}
})
}
I have also tried AVPlayerLooper.
Code is :
var playerLooper: NSObject?
var playerLayer:AVPlayerLayer!
var queuePlayer: AVQueuePlayer?
func playVideo(_ filmName: String){
if let path = Bundle.main.path(forResource: filmName, ofType: "mp4") let url = URL(fileURLWithPath: path)
if #available(tvOS 10.0, *) {
let playerItem = AVPlayerItem(url: url as URL)
self.videoplayer = AVQueuePlayer(items: [playerItem])
self.playerLayer = AVPlayerLayer(player: self.videoplayer)
self.playerLooper = AVPlayerLooper(player: self.videoplayer as! AVQueuePlayer, templateItem: playerItem)
self.blurBgImage.layer.addSublayer(playerLayer!)
self.playerLayer?.frame = self.view.frame
self.videoplayer.volume = 10
self.videoplayer.play()
} else {
videoplayer = AVPlayer(url: url)
videoplayer.play()
loopVideo(videoplayer)
}
}
}
What should i do for seamless looping? Thanks in Advance.
FYI there is sample code here: https://developer.apple.com/library/content/samplecode/avloopplayer/Introduction/Intro.html
#matt's deleted answer works fine for me (on device / simulator) for iOS 10+ devices:
Use AVPlayerLooper. That is exactly what it is for.
https://developer.apple.com/reference/avfoundation/avplayerlooper
Basically it implements AVQueuePlayer for you, constantly updating the
queue so that it never ends.
It seamlessly loops without any white/black blip.
E.g.
private var looper: AVPlayerLooper?
...
let queuePlayer = AVQueuePlayer(playerItem: item)
looper = AVPlayerLooper(player: queuePlayer, templateItem: item)
videoPlayerLayer.player = queuePlayer
If you end up doing this in a reusable cell (e.g. UICollectionView), then make sure you disable looping before cell re-use or you'll get some obscure crashes:
looper?.disableLooping()

AVPlayer & video from documents directory

I've been working on a small project that involves downloading a video file from a web server, copying said file to the documents directory and then playing it via AVPlayer.
Downloading the file to the documents directory hasn't been an issue. I'm able to download the file and save it without issue. However, when it comes to loading the file into AVPlayer, and in doing that I'm playing it in an instance of AVPlayerViewController, the vide controller pops up as it should, but video doesn't load.
I realize that when testing in the simulator the documents directory changes each time you rebuild the project. Which is why I check to see if the file is present before I play, and though I know the file is present, it still refuses to play.
Here is what my player code looks like:
let fileName = downloadURL.characters.split("/").map(String.init).last as String!
let fileNameHD = downloadURLHD.characters.split("/").map(String.init).last as String!
let downloadFilePath = getDocumentsDirectory() + "/" + "\(fileNameHD)"
let checkValidation = NSFileManager.defaultManager()
if checkValidation.fileExistsAtPath(downloadFilePath){
print("video found")
}
let videoFile = NSURL(string:downloadFilePath)
let player = AVPlayer(URL: videoFile!)
let playerController = AVPlayerViewController()
playerController.player = player
playerController.view.frame = self.view.frame
player.play()
self.presentViewController(playerController, animated: true) {
playerController.player!.play()
}
Every time when we rebuild the application Our Document Directory Path change.
So you can't play the video from the old document directory path. So instead of that you have to save the last path component of your URL. Like your document directory url look like this after downloaded the video on this path:-
let videoURL = "/var/mobile/Containers/Data/Application/1F6CDF42-3796-4153-B1E8-50D09D7F5894/Documents/2019_02_20_16_52_47-video.mp4"
var videoPath = ""
if let url = videoURL {
videoPath = url.lastPathComponent
}
print(videoPath)
// It will print the last path of your video url: - "2019_02_20_16_52_47-video.mp4"
Now save this path either in the Core Database or Sqlite or User Defaults where ever you want. Then if you want to play the video again. So you have to get this path from where you save it.
Note:- In Below function you have to pass the last path component of your video. How to call this function.
func playVideo() {
self.startVideoFrom(videoPath:"2019_02_20_16_52_47-video.mp4")
}
// Play Video from path
func startVideoFrom(videoPath: String) {
let outputMineURL = self.createNewPath(lastPath: videoPath)
let player = AVPlayer(url: outputMineURL)
let playerViewController = AVPlayerViewController()
playerViewController.player = player
self.present(playerViewController, animated: true) {
playerViewController.player!.play()
}
}
/// Generate the new document directory path everytime when you rebuild the app and you have to append the last component of your URL.
func createNewPath(lastPath: String) -> URL {
let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let destination = URL(fileURLWithPath: String(format: "%#/%#", documentsDirectory,lastPath))
return destination
}
For more reference, you can see this question:- https://stackoverflow.com/q/47864143/5665836
Try AVPlayer instead of AVPlayerViewController like,
let videoURL = NSURL(string: "your url string")
let player = AVPlayer(URL: videoURL!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = self.view.bounds
self.view.layer.addSublayer(playerLayer)
player.play()
And import AVKit, import AVFoundation.
OR With viewController like this,
let player = AVPlayer(URL: url)
let playerController = AVPlayerViewController()
playerController.player = player
self.addChildViewController(playerController)
self.view.addSubview(playerController.view)
playerController.view.frame = self.view.frame
player.play()
func listVideos() -> [URL] {
let fileManager = FileManager.default
let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let files = try? fileManager.contentsOfDirectory(
at: documentDirectory,
includingPropertiesForKeys: nil,
options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles]
).filter {
[".mp4", ".mkv"].contains($0.pathExtension.lowercased())
}
return files ?? []
}
And Then Play Video Like this I am only playing first URL
let videosURLs = self.listVideos()
let player = AVPlayer(url: videosURLs[0])
let playerViewController = AVPlayerViewController()
playerViewController.player = player
present(playerViewController, animated: true) { () -> Void in
player.play()
}

MPMoviePlayerController doesn't display video

I saw a lot of topics there and always the same problem: it's not displaying at all.
So because I am little stubborn, I want it more
This is my code :
let moviePath = NSBundle.mainBundle().pathForResource("back", ofType:"mp4");
println(moviePath!)
let movieURL = NSURL.fileURLWithPath(moviePath!)
let theMoviePlayer = MPMoviePlayerController(contentURL: movieURL!)
self.view.addSubview(theMoviePlayer.view)
theMoviePlayer.prepareToPlay()
theMoviePlayer.shouldAutoplay = true
theMoviePlayer.fullscreen = true
theMoviePlayer.play()
I checked and I have the movie file in the app's bundle resources.
The video dimension : 640 × 360 pixels
So where it can be from?
Did I forget something important ?
Edit
This new code works but always some problems :
let url = NSBundle.mainBundle().URLForResource("back", withExtension: ".mp4")
let player = MPMoviePlayerViewController(contentURL: url)
presentMoviePlayerViewControllerAnimated(player)
player.moviePlayer.prepareToPlay()
player.moviePlayer.repeatMode = MPMovieRepeatMode.One
player.moviePlayer.shouldAutoplay = true
player.moviePlayer.play()
It show me the video in landscape view and not full screen.
This is how I did it in one of my apps. You might need to call presentMoviePlayerViewControllerAnimated() and pass in the MPMoviePlayerViewController instead of doing addSubview.
let url = NSBundle.mainBundle().URLForResource("back", withExtension: ".mp4")
let player = MPMoviePlayerViewController(contentURL: url)
presentMoviePlayerViewControllerAnimated(player)
player.prepareToPlay()
player.shouldAutoplay = true
player.fullscreen = true
player.moviePlayer.play()
** Resolved **
I resolved addend the line :
player.moviePlayer.view.transform = CGAffineTransformMakeRotation(CGFloat(M_PI / 2))
Of course, it do a rotation of the video. So If it's a simple background animated like clouds or something simple, it's ok.
if there is no issue with the content type of video, call below function. It just works. :)
private func presentVideoVC(){
var url: NSURL = NSURL(string: "http://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v")!
var moviePlayerVC: MPMoviePlayerViewController! = MPMoviePlayerViewController(contentURL: url)
self.presentMoviePlayerViewControllerAnimated(moviePlayerVC)
}
my two cents:
in case of ios9 use https.. (or add exceptions... not good.)
dont call directly on viewDidload, it does not work, call in async to wait some time, allowing controller to be set:
dispatch_async(dispatch_get_main_queue()){
self.playIt()
}
func playIt() {
let urlString = "https://www.ingconti.com/softysit/Spinelli_short.mp4"
let url: NSURL = NSURL(string: urlString)!
let moviePlayerVC: MPMoviePlayerViewController! = MPMoviePlayerViewController(contentURL: url)
moviePlayerVC.moviePlayer.shouldAutoplay = true
self.presentMoviePlayerViewControllerAnimated(moviePlayerVC)
}
note that now MPMoviePlayerViewController is deprecated.

Resources