Воспроизведение локальных видеофайлов в приложении MacOS SwiftUI с помощью AVPlayer - PullRequest
2 голосов
/ 30 мая 2020

Я пытаюсь создать простое приложение SwiftUI, используя XCode 11.5 в macOS 10.15.4, используя AVKit / AVFoundation для воспроизведения видео, хранящихся в локальной файловой системе. Я хотел бы иметь возможность выбрать mov ie на основе пути к файлу, определяемого действиями пользователя (например, выбор из ряда опций меню).

Я работаю с фрагментом кода, найденным здесь: 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)
    }
}

Это отлично работает для выбора файла с помощью объекта «панель», но я не могу понять простое изменение передачи моего собственного значения « 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 »с помощью URL (string :) или Bundle.main. url (forResource :, withExtension:) или другие параметры безуспешно. Приложение компилируется и запускается без ошибок, но оно не отображает видео, а только изображение-заполнитель, указывающее, что файл не был найден.

Я не понимаю, в чем разница между значением "url" возвращается из panel.url и значений, которые я присваиваю вручную. Я проверил содержимое panel.url с помощью .absoluteString, и это в точности соответствует значениям, которые я присваиваю вручную.

Мне, конечно, не хватает чего-то очень очевидного, но я не вижу, что это такое. Кто-нибудь может помочь?

1 Ответ

2 голосов
/ 01 июня 2020

Простое решение этой проблемы: убедитесь, что видеофайл связан с целевым приложением.

Я думал, что делаю это, но, видимо, нет, и способ проверить (XCode 11) - :

  • щелкните видеофайл в окне Project Navigator, а затем

  • отметьте поле Target Membership рядом с целевым приложением в файле
    Окно инспектора

Вот и все. Кредит за этот ответ принадлежит https://github.com/SergioEstevao/, у которого есть решение AVPlayer для приложений SwiftUI: https://github.com/SergioEstevao/SVEVideoUI, которое делает именно то, что я искал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...