저는 swift를 처음 사용하고 앱이 시작되면 AVPlayer를 창 배경으로 사용하여 앱 리소스에서 비디오를 반복하는 Mac OS 앱을 만들려고합니다. 사용자가 메뉴 항목을 선택하거나 버튼을 클릭하면 배경 비디오가 즉시 앱의 리소스에서 다른 비디오로 변경되고 해당 비디오를 창의 배경으로 반복하기 시작합니다.
이 튜토리얼 ( https://youtu.be/QgeQc587w70 )에 따라 앱이 시작되면 첫 번째 비디오를 재생할 수 있었고이 게시물에 따라 비디오 루프 자체를 성공적으로 만들었습니다. ( Looping AVPlayer seamlessly ).
지금 당면한 문제는 메뉴 항목을 선택하거나 버튼을 클릭하면 비디오를 다른 비디오로 변경하는 것입니다. 내가하려고했던 접근 방식은 URL을 변경하고 새 URL을 사용하여 새 AVPlayer를 만들고이 게시물에 따라 playerView.player에 영향을주는 것입니다. ( Swift 버튼을 클릭 할 때 AVPlayer에서 비디오의 URL을 업데이트하는 방법은 무엇입니까?). 그러나 메뉴 항목이 선택 될 때마다 앱이 "thread 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"가 있습니다.
어떤 도움이라도 대단히 감사하겠습니다!
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 에 대한 문서
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다