2017-09-05 1 views
0

나는 신속하고 애플 리케이션을 시작한 후 윈도우의 배경으로 AVPlayer를 사용하여 애플 리케이션의 리소스에서 비디오를 반복하는 맥 OS 애플 리케이션을 만들기 위해 노력하고 새로운입니다. 사용자가 메뉴 항목을 선택하거나 버튼을 클릭하면 배경 비디오가 응용 프로그램의 리소스와 다른 비디오로 즉시 변경되어 해당 비디오를 창 배경으로 반복합니다.Swift Mac OS - 버튼 클릭시 AVPlayer로 다른 비디오 재생/비디오 URL 변경 방법?

이 자습서 (https://youtu.be/QgeQc587w70)에 따라 앱을 실행하고 나면 첫 번째 동영상을 재생할 수 있었으며이 동영상 ({Looping AVPlayer seamlessly})에 이어 원활하게 동영상 루프를 만들었습니다.

지금 직면하고있는 문제는 메뉴 항목을 선택하거나 버튼을 클릭하면 비디오를 다른 것으로 변경하는 것입니다. 내가하려고했던 접근법은 URL을 변경하고 새로운 URL을 사용하여 새로운 AVPlayer를 만들고이 게시물 다음에 playerView.player에 영향을 미치기위한 것입니다 : (Swift How to update url of video in AVPlayer when clicking on a button?). 그러나 메뉴 항목을 선택할 때마다 "스레드 1 exc_bad_instruction (code = exc_i386_invop subcode = 0x0)"오류와 함께 응용 프로그램이 충돌합니다. 이것은 분명히 playerView가 nil이라는 값에 의해 발생합니다. playerView가 xib 파일을 사용하여 만든 컨트롤 드래그로 신속한 파일에 링크 된 AVPlayerView 객체이므로이 작업을 수행하는 다른 적절한 방법을 찾지 못하는 것처럼 보입니다. 할 것. 당신이 이것을위한 이유와 그것을 고치는 방법을 안다면 나에게 도움을 주시거나 제가 위에서 언급 한 것을하기위한 더 나은 방법을 안다면 나에게도 알려주십시오. 어떤 도움을 많이 주시면 감사하겠습니다! 비디오를 빨리 감기/일시 중지 할 수 없습니다

import Cocoa 
import AppKit 
import AVKit 
import AVFoundation 

struct videoVariables { 
    static var videoName = "Test_Video" //declaring the video name as a global variable 
} 

    var videoIsPlaying = true 
    var theURL = Bundle.main.url(forResource:videoVariables.videoName, withExtension: "mp4") //creating the video url 
    var player = AVPlayer.init(url: theURL!) 

class BackgroundWindow: NSWindowController {  
    @IBOutlet weak var playerView: AVPlayerView! // AVPlayerView Linked using control-drag from xib file 
    @IBOutlet var mainWindow: NSWindow! 
    @IBOutlet weak var TempBG: NSImageView! 
    override var windowNibName : String! { 
     return "BackgroundWindow" 
    } 


//function used for resizing the temporary background image and the playerView to the window’s size 
    func resizeBG() { 
     var scrn: NSScreen = NSScreen.main()! 
     var rect: NSRect = scrn.frame 
     var height = rect.size.height 
     var width = rect.size.width 
     TempBG.setFrameSize(NSSize(width: Int(width), height: Int(height))) 
     TempBG.frame.origin = CGPoint(x: 0, y: 0) 
     playerView!.setFrameSize(NSSize(width: Int(width), height: Int(height))) 
     playerView!.frame.origin = CGPoint(x: 0, y: 0) 
    } 

    override func windowDidLoad() { 
     super.windowDidLoad() 
     self.window?.titleVisibility = NSWindowTitleVisibility.hidden //hide window’s title 
     self.window?.styleMask = NSBorderlessWindowMask //hide window’s border 
     self.window?.hasShadow = false //hide window’s shadow 
     self.window?.level = Int(CGWindowLevelForKey(CGWindowLevelKey.desktopWindow)) //set window’s layer as desktopWindow layer 
     self.window?.center() 
     self.window?.makeKeyAndOrderFront(nil) 
     NSApp.activate(ignoringOtherApps: true) 
     if let screen = NSScreen.main() { 
      self.window?.setFrame(screen.visibleFrame, display: true, animate: false) //resizing the window to cover the whole screen 
     } 
     resizeBG() //resizing the temporary background image and the playerView to the window’s size 
     startVideo() //start playing and loop the first video as the window’s background 
    } 

//function used for starting the video again once it has been played fully 
    func playerItemDidReachEnd(notification: NSNotification) { 
     playerView.player?.seek(to: kCMTimeZero) 
     playerView.player?.play() 
    } 

//function used for starting and looping the video  
    func startVideo() { 
     //set the seeking time to be 2ms ahead to prevent a black screen every time the video loops 
     let playAhead = CMTimeMake(2, 100); 
      //loops the video 
      NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: 
       playerView.player?.currentItem, queue: nil, using: { (_) in 
        DispatchQueue.main.async { 

         self.playerView.player?.seek(to: playAhead) 
         self.playerView.player?.play() 
        } 
       }) 

     var playerLayer: AVPlayerLayer? 
     playerLayer = AVPlayerLayer(player: player) 
     playerView?.player = player 
     print(playerView?.player) 
     playerLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill 
     player.play() 


    } 


//changing the url to the new url and create a new AVPlayer then affect it to the playerView.player once the menu item is being selected 
    @IBAction func renderBG(_ sender: NSMenuItem) { 
     videoVariables.videoName = "Test_Video_2" 
     var theNewURL = Bundle.main.url(forResource:videoVariables.videoName, withExtension: "mp4") 
     player = AVPlayer.init(url: theNewURL!) 

     //!!this line crashes the app with the error "thread 1 exc_bad_instruction (code=exc_i386_invop subcode=0x0)" every time the menu item is being selected!! 
     playerView.player = player  
    } 

} 

또한, 배경 비디오가 상호 작용 (예 : 사용자가 있어야되지 않습니다

내 코드는 다음과 같다, 응용 프로그램 충돌 선은 하단에), 사용자 상호 작용으로 인해 발생할 수있는 문제는 무시할 수 있습니다.

"/System/Library/Frameworks/ScreenSaver.framework/Resources/ ScreenSaverEngine.app/Contents/MacOS : 응용 프로그램의 목적은 명령을 실행하는 동일한 효과를 만들어 사용자의 바탕 화면에 비디오를 재생하는 것입니다/ScreenSaverEngine -background "터미널에 있습니다.

도움이 될 것입니다.

답변

0

URL에서 AVPlayer를 만들 필요가 없습니다. 플레이어 재생 대기열을 조작하려면 AVPlayerItem 클래스가 있습니다.

let firstAsset = AVURLAsset(url: firstVideoUrl) 
let firstPlayerItem = AVPlayerItem(asset: firstAsset) 

let player = AVPlayer(playerItem: firstPlayerItem) 

let secondAsset = AVURLAsset(url: secondVideoUrl)  
let secondPlayerItem = AVPlayerItem(asset: secondAsset) 

player.replaceCurrentItem(with: secondPlayerItem) 

문서 AVPlayerItem

에 대한