使用 AVPlayer 在 macOS SwiftUI 应用程序中播放本地视频文件
Playing local video files in macOS SwiftUI application using AVPlayer
我正在尝试在 macOS 10.15.4 上使用 XCode 11.5 创建一个简单的 SwiftUI 应用程序,使用 AVKit/AVFoundation 播放存储在本地文件系统上的视频。我希望能够根据用户操作确定的文件路径 select 电影(例如 select 从一系列菜单选项中选择)。
我正在使用此处找到的代码片段:https://qiita.com/croquette0212/items/eb97e970d1dcfa2932fd
import SwiftUI
import AVKit
import AVFoundation
class VideoItem: ObservableObject {
@Published var player: AVPlayer = AVPlayer()
@Published var playerItem: AVPlayerItem?
func open(_ url: URL) {
let asset = AVAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)
self.playerItem = playerItem
player.replaceCurrentItem(with: playerItem)
}
}
struct PlayerView: NSViewRepresentable {
@Binding var player: AVPlayer
func updateNSView(_ NSView: NSView, context: NSViewRepresentableContext<PlayerView>) {
guard let view = NSView as? AVPlayerView else {
debugPrint("unexpected view")
return
}
view.player = player
}
func makeNSView(context: Context) -> NSView {
return AVPlayerView(frame: .zero)
}
}
struct ContentView: View {
@ObservedObject var videoItem: VideoItem = VideoItem()
var body: some View {
VStack {
if videoItem.playerItem != nil {
PlayerView(player: $videoItem.player)
}
Button(action: {
let panel = NSOpenPanel()
panel.allowedFileTypes = [kUTTypeMovie as String]
DispatchQueue.main.async {
if panel.runModal() == .OK {
guard let url = panel.url else {
return
}
self.videoItem.open(url)
}
}
}) {
Text("Open")
}
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
这对于使用 "panel" 对象 selecting 文件非常有效,但我无法弄清楚将我自己的 "url" 值传递给 videoItem.open().
我试过更换方块:
let panel = NSOpenPanel()
panel.allowedFileTypes = [kUTTypeMovie as String]
DispatchQueue.main.async {
if panel.runModal() == .OK {
guard let url = panel.url else {
return
}
self.videoItem.open(url)
}
}
,使用 URL(string:) 或 Bundle.main.url(forResource:, withExtension: ) 或其他选项定义我的 "url" 值,但没有任何成功。该应用程序编译并运行没有错误,但它不显示视频,仅显示一个占位符图像,表示找不到该文件。
我不明白从 panel.url 返回的 "url" 的值和我手动分配的值之间有什么区别。我已经使用 .absoluteString 检查了 panel.url 的内容,这与我手动分配的值完全匹配。
我肯定遗漏了一些非常明显的东西,但我看不到它是什么。拜托,有人可以提供一些帮助吗?
此问题的简单解决方案:确保视频文件与目标应用程序捆绑在一起。
我以为我这样做了,但显然不是,检查 (XCode 11) 的方法是:
在项目导航器中单击视频文件 window 然后,
勾选文件中目标应用程序旁边的目标成员资格框
检查员 window
就是这样。此答案的功劳属于 https://github.com/SergioEstevao/ who has a AVPlayer solution for SwiftUI applications: https://github.com/SergioEstevao/SVEVideoUI,它完全符合我的要求。
我正在尝试在 macOS 10.15.4 上使用 XCode 11.5 创建一个简单的 SwiftUI 应用程序,使用 AVKit/AVFoundation 播放存储在本地文件系统上的视频。我希望能够根据用户操作确定的文件路径 select 电影(例如 select 从一系列菜单选项中选择)。
我正在使用此处找到的代码片段:https://qiita.com/croquette0212/items/eb97e970d1dcfa2932fd
import SwiftUI
import AVKit
import AVFoundation
class VideoItem: ObservableObject {
@Published var player: AVPlayer = AVPlayer()
@Published var playerItem: AVPlayerItem?
func open(_ url: URL) {
let asset = AVAsset(url: url)
let playerItem = AVPlayerItem(asset: asset)
self.playerItem = playerItem
player.replaceCurrentItem(with: playerItem)
}
}
struct PlayerView: NSViewRepresentable {
@Binding var player: AVPlayer
func updateNSView(_ NSView: NSView, context: NSViewRepresentableContext<PlayerView>) {
guard let view = NSView as? AVPlayerView else {
debugPrint("unexpected view")
return
}
view.player = player
}
func makeNSView(context: Context) -> NSView {
return AVPlayerView(frame: .zero)
}
}
struct ContentView: View {
@ObservedObject var videoItem: VideoItem = VideoItem()
var body: some View {
VStack {
if videoItem.playerItem != nil {
PlayerView(player: $videoItem.player)
}
Button(action: {
let panel = NSOpenPanel()
panel.allowedFileTypes = [kUTTypeMovie as String]
DispatchQueue.main.async {
if panel.runModal() == .OK {
guard let url = panel.url else {
return
}
self.videoItem.open(url)
}
}
}) {
Text("Open")
}
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
这对于使用 "panel" 对象 selecting 文件非常有效,但我无法弄清楚将我自己的 "url" 值传递给 videoItem.open().
我试过更换方块:
let panel = NSOpenPanel()
panel.allowedFileTypes = [kUTTypeMovie as String]
DispatchQueue.main.async {
if panel.runModal() == .OK {
guard let url = panel.url else {
return
}
self.videoItem.open(url)
}
}
,使用 URL(string:) 或 Bundle.main.url(forResource:, withExtension: ) 或其他选项定义我的 "url" 值,但没有任何成功。该应用程序编译并运行没有错误,但它不显示视频,仅显示一个占位符图像,表示找不到该文件。
我不明白从 panel.url 返回的 "url" 的值和我手动分配的值之间有什么区别。我已经使用 .absoluteString 检查了 panel.url 的内容,这与我手动分配的值完全匹配。
我肯定遗漏了一些非常明显的东西,但我看不到它是什么。拜托,有人可以提供一些帮助吗?
此问题的简单解决方案:确保视频文件与目标应用程序捆绑在一起。
我以为我这样做了,但显然不是,检查 (XCode 11) 的方法是:
在项目导航器中单击视频文件 window 然后,
勾选文件中目标应用程序旁边的目标成员资格框
检查员 window
就是这样。此答案的功劳属于 https://github.com/SergioEstevao/ who has a AVPlayer solution for SwiftUI applications: https://github.com/SergioEstevao/SVEVideoUI,它完全符合我的要求。