I have a desktop (macOS) application that reads video clips (.mov, .m4v, .mp4...). The application reads a video clip as an avAsset object as follows.
import Cocoa
import AVKit
class VideoViewController: NSViewController {
var videoPlayer: AVPlayer!
var videoURL: URL?
var videoDur: Double!
var videoFrameRate: Float!
var videoData: Data!
var naturalSize: CGSize!
var hasVideo = false
#IBOutlet weak var moviePlayer: AVPlayerView!
#IBOutlet weak var layerView: LayerView!
func readVideoClip(url: URL) {
let avAsset = AVURLAsset(url: url)
let videoTracks = avAsset.tracks(withMediaType: .video)
if videoTracks.count > 0 {
let videoTrack = videoTracks[0]
let playerItem = AVPlayerItem(asset: avAsset)
let avFrameRate = videoTrack.nominalFrameRate
videoPlayer = AVPlayer(playerItem: playerItem)
moviePlayer.player = videoPlayer
moviePlayer.isHidden = false
naturalSize = videoTrack.naturalSize
/* variables */
hasVideo = true
videoURL = url
videoDur = totalDuration
videoFrameRate = avFrameRate
}
}
}
My question is whether or not there is a way of telling whether or not the selected video clip is copy-protected. The application is already available at Mac App Store. I've submitted a software update for it. And they've rejected it by saying the following.
We found the app allows the user to select copy protected files such
as .m4v and does not inform the user that the file cannot be
converted/saved/revised.
It seems that AVPlayerView has canBeginTrimming property. And the following returns false with a non-protected video clip.
if !moviePlayer.canBeginTrimming {
// it returns false
}
I guess an extreme measure will be to not accept the M4V format when the user selects a video clip. Thanks.
Related
I've spent a few days trying different combinations of code I've come across on StackOverflow to no avail.
Here's the code I'm currently using to display MP4 videos (looped, no sound) within a UIView component.
import Foundation
import AVFoundation
import AVKit
class VideoPlayerLooped {
public var videoPlayer:AVQueuePlayer?
public var videoPlayerLayer:AVPlayerLayer?
var playerLooper: NSObject?
var queuePlayer: AVQueuePlayer?
func playVideo(fileName:String, inView:UIView)
{
if let path = Bundle.main.path(forResource: fileName, ofType: "mp4")
{
let url = URL(fileURLWithPath: path)
let playerItem = AVPlayerItem(url: url as URL)
_ = try? AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: .default, options: .mixWithOthers)
videoPlayer = AVQueuePlayer(items: [playerItem])
videoPlayer?.isMuted = true
videoPlayer?.preventsDisplaySleepDuringVideoPlayback = false
playerLooper = AVPlayerLooper(player: videoPlayer!, templateItem: playerItem)
videoPlayerLayer = AVPlayerLayer(player: videoPlayer)
videoPlayerLayer!.frame = inView.bounds
inView.layer.addSublayer(videoPlayerLayer!)
videoPlayer?.play()
}
}
func remove()
{
videoPlayerLayer?.removeFromSuperlayer()
}
}
Although this solution works to play and loop MP4s, it doesn't provide the user with an option to click the video for a full screen version (landscape rotation) with controls.
Any recommendations or light that can be shed will be most helpful!
You could use an AVPlayerViewController. Apple has a tutorial on the subject in the Xcode help system. It's also available online. Check this link.
I am currently playing a video from local with bundle URL.
private let videoURL = Bundle.main.path(forResource: "video", ofType:"mp4")
here is the setupPlayer method:
player = AVPlayer(url: URL(fileURLWithPath: url))
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = videoContainerView.layer.bounds
playerLayer.videoGravity = .resize
I can preview the video and sound but Xcode generates some errors. After some searching on internet, I can not find anything about how to solve them.
2021-01-31 15:56:25.026534+0300 PixeryCase[72428:5712733] [] [15:56:25.026] FigSubtitleSampleCreateFromPropertyList signalled err=50 (kFigCFBadPropertyListErr) (NULL or bad plist) at /Library/Caches/com.apple.xbs/Sources/EmbeddedCoreMedia_Sim/EmbeddedCoreMedia-2765.6/Prototypes/ClosedCaptions/FigCaptionCommand.c:792
2021-01-31 15:56:25.233948+0300 PixeryCase[72428:5712809] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x600002a1be40>
2021-01-31 15:56:25.563638+0300 PixeryCase[72428:5712816] [] [15:56:25.564] VMC2SetProperty signalled err=-12823 (kVMCParameterErr) (not a CFString) at /Library/Caches/com.apple.xbs/Sources/EmbeddedCoreMedia_Sim/EmbeddedCoreMedia-2765.6/Prototypes/MediaConverter/VideoMediaConverter2.c:7105
please add
let playerLayer = AVPlayerLayer(player: player)
view.layer?.addSublayer(playerLayer)
A convenient way of using AVPlayerLayer in iOS ,
is as the backing layer for a UIView as illustrated in the following code example:
class PlayerView: UIView {
var player: AVPlayer? {
get {
return playerLayer.player
}
set {
playerLayer.player = newValue
}
}
var playerLayer: AVPlayerLayer {
return layer as! AVPlayerLayer
}
// Override UIView property
override static var layerClass: AnyClass {
return AVPlayerLayer.self
}
}
I have a custom video recording view controller, in which I save using a URL:
Sample URL: file:///var/mobile/Containers/Data/Application/802497BB-8413-4245-B33A-708EF8DD9CAF/Documents/FA6AF78A-2692-4CC8-8BE2-7F18140C3C98.mp4
The URL is generated using these functions:
// Gets the directory that the video is stored in
func getPathDirectory() -> URL {
// Searches a FileManager for paths and returns the first one
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentDirectory = paths[0]
return documentDirectory
}
func generateURL() -> URL? {
let path = getPathDirectory().appendingPathComponent(NSUUID().uuidString + ".mp4")
return path
}
I then replay the video once in a separate playback controller, and it works no problem. I have included it right below:
import AVFoundation
class VideoPlaybackController: UIViewController {
let avPlayer = AVPlayer()
var avPlayerLayer: AVPlayerLayer!
var videoURL: URL!
#IBOutlet weak var videoView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// print("VideoPlaybackController: \(videoURL!)")
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer.frame = view.bounds
avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoView.layer.insertSublayer(avPlayerLayer, at: 0)
view.layoutIfNeeded()
let playerItem = AVPlayerItem(url: self.videoURL as URL)
avPlayer.replaceCurrentItem(with: playerItem)
avPlayer.play()
}
}
While the video works, after some time, the video cannot be replayed, even though I saved it within the document directory. I downloaded the xcappdata and looked within the contents of the app, and saw that the video file is still there, so I am confused as to why the video is not available after some time.
Is there something that I am missing? Thank you for your time.
I'm trying to get a video I have in my project to play in my macOS application using swift. Here is my code:
import Cocoa
import AVKit
import AVFoundation
class ViewController: NSViewController {
var player : AVPlayer!
var avPlayerLayer : AVPlayerLayer!
#IBOutlet weak var videoPlayer: AVPlayerView!
override func viewDidLoad() {
super.viewDidLoad()
guard let path = Bundle.main.path(forResource: "Background", ofType:"mp4") else {
debugPrint("Not found")
return
}
let playerURL = AVPlayer(url: URL(fileURLWithPath: path))
let playerView = AVPlayerView()
playerView.player = playerURL
playerView.player?.play()
}
}
I also have an AVPlayerView in my storyboard that I have connected to my viewcontroller.
It builds and runs fine but when I run it nothing shows up. I just get a black screen.
Any help is appreciated. Thanks!
The problem is this line:
let playerView = AVPlayerView()
Instead of configuring the player view that is in your interface, you make a whole new separate player view — and then you throw it away.
I am using AVFoundation kit to play a local video
I tried this code:
import UIKit
import AVFoundation
class ViewController: UIViewController {
var player: AVPlayer?
#IBOutlet weak var videoViewContainer: UIView!
override func viewDidLoad() {
super.viewDidLoad()
initializeVideoPlayerWithVideo()
}
func initializeVideoPlayerWithVideo() {
// get the path string for the video from assets
let videoString:String? = Bundle.main.path(forResource: "Air Bike", ofType: "mov")
guard let unwrappedVideoPath = videoString else {return}
// convert the path string to a url
let videoUrl = URL(fileURLWithPath: unwrappedVideoPath)
// initialize the video player with the url
self.player = AVPlayer(url: videoUrl)
// create a video layer for the player
let layer: AVPlayerLayer = AVPlayerLayer(player: player)
// make the layer the same size as the container view
layer.frame = videoViewContainer.bounds
// make the video fill the layer as much as possible while keeping its aspect size
layer.videoGravity = AVLayerVideoGravity.resizeAspectFill
// add the layer to the container view
videoViewContainer.layer.addSublayer(layer)
}
#IBAction func playVideoButtonTapped(_ sender: UIButton) {
// play the video if the player is initialized
player?.play()
}
}
I've trying a few different approaches and I'm still getting the same error message can someone How can I resolve this issue?
func initializeVideoPlayerWithVideo() {
guard let path = Bundle.main.path(forResource: "jagdeep", ofType:".MOV") else {
debugPrint("video.m4v not found")
return
}
self.player = AVPlayer(url: URL(fileURLWithPath: path))
// create a video layer for the player
let layer: AVPlayerLayer = AVPlayerLayer(player: player)
// make the layer the same size as the container view
layer.frame = videoViewContainer.bounds
// make the video fill the layer as much as possible while keeping its aspect size
layer.videoGravity = AVLayerVideoGravity.resizeAspectFill
// add the layer to the container view
videoViewContainer.layer.addSublayer(layer)
player?.play()
}
HERE IS MY VIDEO NAME jagdeep and type .MOV AND its working on my side. It's problem in your code where you using type mov. I just drag a video name jagdeep.MOV to my project and use Your code. its ok
**use**
layer.frame = videoViewContainer.layer.bounds
instead of
// make the layer the same size as the container view
layer.frame = videoViewContainer.bounds
Thank you for your response seems like the file cannot be found here is a screenshot from my project what could be the reason the video is located in my main folder! Screenshot