There is so much stuff in Stackoverflow about playing videos in cell, that every person may feel confused, especially that most of question are not solved and it looks like that every developer gives up.
So I wanted to create new question where there will be up-to-date answers.
Objective:
Play video in UITableViewCell or UICollectionViewCell when user taps cell (yes, this is simplified version, this is not about autplay).
Solution:
I think everyone agrees that we should use AVPlayer instead of deprecated MPMoviePlayerController.
Cell should have layer where AVPlayer can be assigned, so in my code while creating cell I added this code:
VideoCell.swift
let layer = AVPlayerLayer()
layer.backgroundColor = UIColor.clear.cgColor
layer.videoGravity = AVLayerVideoGravityResizeAspectFill
Now when cell is tapped I'm using this code:
ViewController.swift
cell.playerLayer.player = player
player.replaceCurrentItem(with: AVPlayerItem(asset: asset))
player.play()
Where player is global instance of AVPlayer and asset is AVAsset initialized with video URL.
It would work fine, but AVPlayer needs time to download info and buffer some part of video, and what user gets is delay. So we can think about one solution, which is downloading video first and playing it locally when users taps in cell.
Question:
Is it really good approach to downloading every video in data source and then playing it locally? When should we remove it from device? Facebook and Instagram looks like they download only part of the video first, is there any who can share own experience?
Objective-C code will be appreciated too.
Related
Goal:
To add youtube like preview feature when user seeks manually using the player seek bar.
From what I understand so far is that I will have to add "I-Frame only playlist" to my stream to enable trick play but I am not able to figure out how I will be using this to show the preview view on the video player?
Other solutions I considered:
AVAssetImageGenerator: It does not work on streams. Explained here.
This says if my .m3u8 file contains "I-Frame only playlist", AVAssetImageGenerator will start returning the snapshot, but even if it does, generating thumbnails of a complete 1 hour video upfront is just not optimal.
AVPlayerItemVideoOutput This also seems like a very brut force way to approach the problem as I need thumbnails of almost complete video.
Current player implementation:
I have added AVPlayerLayer as a sublayer to my view controller's view and added custom controls on top of it.
I am thinking of using something like this https://github.com/pbs/iframe-playlist-generator to add the I-Frame playlist.
PS: I am new to this, so if I have made any wrong assumption, please let me know.
Also, any links or references to some reading material I can use to dive in deeper are appreciated. Thanks.
I'm creating AVPlayer view to watch the stream from CCTV. And I want to make playback controls in a video like in Photos app at iPhone(open Photos, play some video, at the bottom, it will be UIScrollView with some screenshots of your video) like at image below.
May I ask you some help on how to create something like this?
And this is my first question here, so sorry if something wrong. =)
ScrollView playback
AVPlayer cannot do this for streaming. The suggestion made on snapshots would also not be close to your want of getting the same behaviour as on local preview of videos in the Photos App on iOS.
If you are looking for this kind of experience I would recommend heading over to movi.ai to get your hands on our cross platform solution with this ready out of the box.
We are displaying a UIImagePickerController for users to choose (and crop) a video for use within our app. Recently users have been experiencing issues trying to crop videos, with the start time handle becoming almost impossible to drag.
It seems that the Photos app doesn't have this issue because the video timeline (and crop selection) is moved to the bottom of the screen.
I assume this has to do with the new notification centre gestures that were added for the iPhone X. I believe this question here is related to the issue we're experiencing.
Anyone else having this issue, or have a way to get around it? Since this is a stock UIViewController I can't see how we can get around the issue without building our own custom video picker/cropper.
I was having the same issue and I decided to disable the UIImagePickerController editing and catch the video path in the UIImagePIckerController's didFinishPickingMediaWithInfo, and then use UIVideoEditorController to edit the video. This is a quick example:
if UIVideoEditorController.canEditVideo(atPath: videoPath) {
let editController = UIVideoEditorController()
editController.videoPath = videoPath
editController.delegate = self
present(editController, animated:true)
}
For more information about UIVideoEditorController, check Apple's documentation: https://developer.apple.com/documentation/uikit/uivideoeditorcontroller?
I have a one button and AVPlayer. After button click I record a video using DBAttachmentPickerController and I want to load it to the AVPlayer.
In function below I try to load it:
func refresh(attachmentInfo: AttachmentInfo) {
self.videoLayer.player = nil
if let url = attachmentInfo.url {
self.player = AVPlayer(url: url) // line A
self.videoLayer.player = self.player // line B
}
}
In 6/10 cases it works fine, but sometimes the video doesn't load to AVPlayer.
When I set breakpoints in line A and B it works always.
Any ideas?
I also hit this exact issue as yours. In my case the AVPlayer and AVPlayerLayer were inside tableview cells which made the problem worse. However, I was using an API which returned the actual video URL, and an Image URL which consisted of the video's first frame's image. In the tableview cell logic, I first attempt to load the video into AVPlayer and then check if the AVPlayer has any .video assets, if it didn't then I simply load the Image from the other URL into the UIView (using a UIImageView of course) with a "Play" button image in the center of the Image. When the user taps the play button the selector function should try to load the AVPlayer again with the video URL. If the video loads and AVPlayer has assets then play() else simply return (and possibly alert the user that the video can't be loaded).
If you do not have the image of the first frame of the video, you can simply use a placeholder image and a button.
The way to check if the player has a video or not-
if player.currentItem?.asset.tracks(withMediaType: .video).count == 0{
print("Oops! no video here")
//load an image, and add a button here
}else{
//do whatever needs to be done if video is available
}
Unfortunately, there isn't much else that can be done here unless you have some solid networking code where in you can download the video in a utility thread and store it in cache, but then again you have to be cognizant about the user's data usage, spawning too many download threads etc.
For image caching in the UITableView cell, I used SDWebImage library from Github so that I can be (somewhat) assured that my image (for the video) atleast would be cached in case of bad/slow network, or network interruptions.
I Need to play a video when the view load but, other code i have try to do the video player comes up. I want to play the video in the UIVIEW. Can someone please help!
You will need to use an AVPlayer, specifying an AVPlayerItem. This should allow you to use multiple AV items within a single view.
Basically, everything is explained here:
https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html