0

I am trying to get my macOS Cocoa Application Xcode project to play some video when I feed it a specified URL.

To simplify the question lets just use an empty Xcode project.

I want to achieve the same level of control as I am able to get using AVPlayerViewController() in my iOS Single View Application. Within that app I am currently using the solution offered here.

However, only the second example works in my macOS Cocoa Application when adapted like so:

import Cocoa
import AVFoundation
import AVKit

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
        let player = AVPlayer(url: videoURL!)
        let playerLayer = AVPlayerLayer(player: player)
        playerLayer.frame = self.view.bounds
        self.view.layer?.addSublayer(playerLayer)
        player.play()

    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }


}

This option however has 2 downsides:

  1. It creates a repetitive error message in the console:

    2017-06-27 18:22:06.833441+0200 testVideoOnmacOS[24456:1216773] initWithSessionInfo: XPC connection interrupted
    2017-06-27 18:22:06.834830+0200 testVideoOnmacOS[24456:1216773] startConfigurationWithCompletionHandler: Failed to get remote object proxy: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.rtcreportingd" UserInfo={NSDebugDescription=connection to service named com.apple.rtcreportingd}
    
  2. This AVPlayer solution does not offer the same control as the AVPlayerViewController() solution.

So I attempted to get the following AVPlayerViewController() solution to work. But it fails:

import Cocoa
import AVFoundation
import AVKit

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
        let player = AVPlayer(url: videoURL!)
        let playerViewController = AVPlayerViewController()
        playerViewController.player = player
        self.present(playerViewController, animated: true) {
            playerViewController.player!.play()
        }

    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }


}

The error I am getting is:

Use of unresolved identifier 'AVPlayerViewController' - Did you mean 'AVPlayerViewControlsStyle'?

I have tried to work around this in many different ways. It will be confusing if I spell them all out. My prominent problem seems to be that the vast majority of online examples are iOS based.

Thus, the main question:

How would I be able to successfully use AVPlayerViewController within my Xcode macOS Cocoa Application?

Montmons
  • 1,416
  • 13
  • 44
  • 1
    `AVPlayerViewController` only exists in iOS and tvOS. You need to use `AVPlayer` and add its layer as a sublayer of your `NSViewController`. Your two errors appear to have nothing to do with AVFoundation. – JAL Jun 27 '17 at 17:48
  • 1
    Try AVPlayerView https://developer.apple.com/documentation/avkit/avplayerview – ninjaproger Jun 27 '17 at 18:49

1 Answers1

2

Yes, got it working!

Thnx to ninjaproger's comment.

This seems to work in order to get a video from the web playing / streaming on a macOS Cocoa Application in Xcode.

First, create a AVKitPlayerView on your storyboard and link it as an IBOutlet to your NSViewController.

Then, simply apply this code:

import Cocoa
import AVFoundation
import AVKit

class ViewController: NSViewController {
    @IBOutlet var videoView: AVPlayerView!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let videoURL = URL(string: "https://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4")
        let player = AVPlayer(url: videoURL!)
        let playerViewController = videoView
        playerViewController?.player = player
        playerViewController?.player!.play()
    
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }


} 

Update august 2021

Ok, it's been a while since this answer has been up and I am no longer invested in it. But it seems others still end up here and the solution needs a bit more work to work properly at times.

With thanks to @SouthernYankee65:

What is needed sometimes is to go to the project file and on the Signing & Capabilities tab check Outgoing Connection (Client). Then in the info.plist add App Transport Security Settings dictionary property, then add Allows Arbitrary Loads boolean property and set it to YES.

The video now plays. However, some errors in the console might occur.

Montmons
  • 1,416
  • 13
  • 44
  • I have exactly same code as above but I get the following errors: 2017-11-10 19:24:39.624713-0800 AVPlayer[3611:195886] initWithSessionInfo: XPC connection interrupted 2017-11-10 19:24:39.625393-0800 AVPlayer[3611:195886] startConfigurationWithCompletionHandler: Failed to get remote object proxy: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.rtcreportingd" UserInfo={NSDebugDescription=connection to service named com.apple.rtcreportingd} – Neal Davis Nov 11 '17 at 03:28
  • after the above is the following: 017-11-10 19:24:39.625509-0800 AVPlayer[3611:195886] 2017-11-10 19:24:52.886022-0800 AVPlayer[3611:195887] sendMessageWithCategory: Failed to get remote object proxy: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.rtcreportingd" UserInfo={NSDebugDescription=connection to service named com.apple.rtcreportingd} 2017-11-10 19:24:52.886206-0800 AVPlayer[3611:195887] initWithSessionInfo: XPC connection interrupted 2017-11-10 19:24:52.886320-0800 AVPlayer[3611:195810] initWithSessionInfo: XPC connection invalid – Neal Davis Nov 11 '17 at 03:28
  • This doesn't work for me either. I followed https://developer.apple.com/forums/thread/677002?page=1#668659022 and I get the same errors as @NealDavis above. The above code is nearly the same code as the code in the Apple Document. – SouthernYankee65 Mar 29 '21 at 23:54
  • Okay, after doing a little more searching, I got the code above to work. I am using Xcode 12.4 on macOS Big Sur 11.2.3. I had to go to the project file and on the Signing & Capabilities tab I checked Outgoing Connection (Client). Then I went to the info.plist and added App Transport Security Settings dictionary property, then added Allows Arbitrary Loads boolean property and set it to YES. The video in the answer now plays. However, the errors reported in the console that @NealDavis and I reported still occur. But, at least now it plays! – SouthernYankee65 Mar 30 '21 at 00:10