上传视频到Firebase使用Swift UI

huangapple go评论58阅读模式
英文:

Upload Video to Firebase Using Swift UI

问题

这是我从设备中选择视频并将其上传到Firebase的代码:

import SwiftUI
import PhotosUI
import FirebaseStorage

class ShareVideo: NSObject, ObservableObject {
    
    @Published var videoURL: URL?
    
    func selectVideo() {

        PHPhotoLibrary.requestAuthorization { status in
            switch status {
            case .authorized:
                print("访问权限已授权。")
            case .denied, .restricted:
                print("访问权限被拒绝。")
            case .notDetermined:
                print("权限未确定。")
            @unknown default:
                fatalError("出现新的授权状态。")
            }
        }
        
        var configuration = PHPickerConfiguration()
        configuration.filter = .videos
        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = self
        UIApplication.shared.windows.first?.rootViewController?.present(picker, animated: true)
    }

    
    func uploadVideo() {
        guard let videoURL = videoURL else {
            return
        }
        let storage = Storage.storage()
        let storageRef = storage.reference()
        let videoRef = storageRef.child("videos/\(UUID().uuidString).mp4")
        let metadata = StorageMetadata()
        metadata.contentType = "video/mp4"

        videoRef.putFile(from: videoURL, metadata: metadata) { metadata, error in
            if let error = error {
                print("上传视频错误: \(error.localizedDescription)")
            } else {
                print("视频上传成功。")
            }
        }
    }
}

extension ShareVideo: PHPickerViewControllerDelegate {
    
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        
        picker.dismiss(animated: true)
        guard let result = results.first else {
            return
        }
        result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, error in
            if let error = error {
                print("加载视频错误: \(error.localizedDescription)")
            } else if let url = url {
                DispatchQueue.main.async {
                    self.videoURL = url
                }
            }
        }
        
    }
}

struct ShareVideoView: View {
    @StateObject private var shareVideo = ShareVideo()
    
    var body: some View {
        VStack{
            Button(action: {
                shareVideo.selectVideo()
            }){
                Text("选择视频")
            }
            
            Button("上传视频") {
                shareVideo.uploadVideo()
            }
        }
    }
}

struct ShareVideoView_Previews: PreviewProvider {
    static var previews: some View {
        ShareVideoView()
    }
}

我收到以下错误消息:
上传视频错误: 文件URL: file:///Users/hitesh/Library/Developer/CoreSimulator/Devices/B28A566B-E082-4802-87CA-E2044ECCE57C/data/Containers/Data/Application/25CE276A-BD92-4D0C-9FBE-C594E9C05E90/tmp/.com.apple.Foundation.NSItemProvider.8pCkyb/SampleVideo_1280x720_1mb.mp4 无法访问。请确保文件URL不是目录、符号链接或无效URL。

英文:

Here is my code to pick the video from device and upload it to firebase


import SwiftUI
import PhotosUI
import FirebaseStorage
class ShareVideo: NSObject, ObservableObject {
@Published var videoURL: URL?
func selectVideo() {
PHPhotoLibrary.requestAuthorization { status in
switch status {
case .authorized:
print("Access granted.")
case .denied, .restricted:
print("Access denied.")
case .notDetermined:
print("Authorization not determined.")
@unknown default:
fatalError("New authorization status is available.")
}
}
var configuration = PHPickerConfiguration()
configuration.filter = .videos
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
UIApplication.shared.windows.first?.rootViewController?.present(picker, animated: true)
}
func uploadVideo() {
guard let videoURL = videoURL else {
return
}
let storage = Storage.storage()
let storageRef = storage.reference()
let videoRef = storageRef.child("videos/\(UUID().uuidString).mp4")
let metadata = StorageMetadata()
metadata.contentType = "video/mp4"
videoRef.putFile(from: videoURL, metadata: metadata) { metadata, error in
if let error = error {
print("->>>>\(videoURL)")
print("Error uploading video: \(error.localizedDescription)")
} else {
print("Video uploaded successfully.")
}
}
}
}
extension ShareVideo: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true)
guard let result = results.first else {
return
}
result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, error in
if let error = error {
print("Error loading video: \(error.localizedDescription)")
} else if let url = url {
DispatchQueue.main.async {
self.videoURL = url
}
}
}
}
}
struct ShareVideoView: View {
@StateObject private var shareVideo = ShareVideo()
var body: some View {
VStack{
Button(action: {
shareVideo.selectVideo()
}){
Text("Select Video")
}
Button("Upload Video") {
shareVideo.uploadVideo()
}
}
}
}
struct ShareVideoView_Previews: PreviewProvider {
static var previews: some View {
ShareVideoView()
}
}

I am getting the following error
Error uploading video: File at URL: file:///Users/hitesh/Library/Developer/CoreSimulator/Devices/B28A566B-E082-4802-87CA-E2044ECCE57C/data/Containers/Data/Application/25CE276A-BD92-4D0C-9FBE-C594E9C05E90/tmp/.com.apple.Foundation.NSItemProvider.8pCkyb/SampleVideo_1280x720_1mb.mp4 is not reachable. Ensure file URL is not a directory, symbolic link, or invalid url.

答案1

得分: 0

这是您提供的代码的翻译:

我不知何故设法实现了它

import PhotosUI
import SwiftUI
import UIKit
import AVKit
import ImageCaptureCore
import AVFoundation
import FirebaseStorage

struct VideoPicker: View {
    @State private var videoURL: URL?
    @State private var isShowingVideoPicker = false

    private func pickVideo() {
        isShowingVideoPicker = true
    }

    private func handleVideoPickerResult(_ videoURL: URL) {
        self.videoURL = videoURL
    }

    // 为Firebase设置注册应用程序委托
    var body: some View {
        VStack {
            Button(action: pickVideo) {
                Text("从相册选择视频")
            }.padding()
            .sheet(isPresented: $isShowingVideoPicker) {
                ImagePickerDelegate(sourceType: .photoLibrary, mediaTypes: ["public.movie"], didPickVideo: handleVideoPickerResult)
            }

            if let videoURL = videoURL {
                VideoPlayerView(videoURL: videoURL)
                    .frame(height: 200)
            } else {
                Text("点击按钮选择视频")
                    .padding()
            }

            Button("上传视频") {
                if let videoURL = videoURL {
                    upload(file: videoURL) { url in
                        print(url)
                    }
                }
            }
            .padding()
        }
    }
}

extension VideoPicker {
    func upload(file: URL, completion: @escaping ((_ url: URL?) -> ())) {
        let name = "\(UIDevice.current.identifierForVendor?.uuidString ?? "")\(UUID().uuidString).mp4"
        do {
            let data = try Data(contentsOf: file)

            let storageRef = Storage.storage().reference().child("Videos").child(name)
            if let uploadData = data as Data? {
                let metaData = StorageMetadata()
                metaData.contentType = "video/mp4"
                storageRef.putData(uploadData, metadata: metaData) { (metadata, error) in
                    if let error = error {
                        completion(nil)
                    } else {
                        storageRef.downloadURL { (url, error) in
                            guard let downloadURL = url else {
                                completion(nil)
                                return
                            }
                            completion(downloadURL)
                        }
                        print("上传成功")
                    }
                }
            }
        } catch let error {
            print(error)
        }
    }
}

struct ImagePickerDelegate: UIViewControllerRepresentable {
    let sourceType: UIImagePickerController.SourceType
    let mediaTypes: [String]
    let didPickVideo: (URL) -> Void

    func makeUIViewController(context: Context) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.sourceType = sourceType
        picker.mediaTypes = mediaTypes
        picker.delegate = context.coordinator
        return picker
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}

    func makeCoordinator() -> Coordinator {
        Coordinator(didPickVideo: didPickVideo)
    }

    final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        let didPickVideo: (URL) -> Void

        init(didPickVideo: @escaping (URL) -> Void) {
            self.didPickVideo = didPickVideo
        }

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            if let videoURL = info[.mediaURL] as? URL {
                didPickVideo(videoURL)
            }
            picker.dismiss(animated: true)
        }

        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            picker.dismiss(animated: true)
        }
    }
}

struct VideoPlayerView: View {
    var videoURL: URL

    var body: some View {
        VideoPlayer(player: AVPlayer(url: videoURL))
            .onAppear {
                // 视图出现时自动播放视频
                let player = AVPlayer.shared()
                player.play()
            }
            .onDisappear {
                // 视图消失时暂停视频
                let player = AVPlayer.shared()
                player.pause()
            }
    }
}

extension AVPlayer {
    static func shared() -> AVPlayer {
        struct Singleton {
            static let instance = AVPlayer()
        }
        return Singleton.instance
    }
}

struct VideoPickerView_Previews: PreviewProvider {
    static var previews: some View {
        Homeview()
    }
}

请注意,我已经将文本中的 HTML 实体代码(如")替换为双引号。

英文:

I have somehow managed to achieve it

import PhotosUI
import SwiftUI
import UIKit
import AVKit
import ImageCaptureCore
import AVFoundation
import FirebaseStorage
struct VideoPicker: View {
@State private var videoURL: URL?
@State private var isShowingVideoPicker = false
private func pickVideo() {
isShowingVideoPicker = true
}
private func handleVideoPickerResult(_ videoURL: URL) {
self.videoURL = videoURL
}
// register app delegate for Firebase setup
var body: some View {
VStack {
Button(action: pickVideo) {
Text("Select Video from Gallery")
}.padding()
.sheet(isPresented: $isShowingVideoPicker) {
ImagePickerDelegate(sourceType: .photoLibrary, mediaTypes: ["public.movie"], didPickVideo: handleVideoPickerResult)
}
if let videoURL = videoURL {
VideoPlayerView(videoURL: videoURL)
.frame(height: 200)
} else {
Text("Tap the button to select a video")
.padding()
}
Button("Upload Video") {
if let videoURL = videoURL {
upload(file: videoURL) { url in
print(url)
}
}
}
.padding()
}
}
}
extension VideoPicker {
func upload(file: URL, completion: @escaping ((_ url : URL?) -> ())) {
let name = "\(UIDevice.current.identifierForVendor?.uuidString)!\(UUID().uuidString).mp4"
do {
let data = try Data(contentsOf: file)
let storageRef =
Storage.storage().reference().child("Videos").child(name)
if let uploadData = data as Data? {
let metaData = StorageMetadata()
metaData.contentType = "video/mp4"
storageRef.putData(uploadData, metadata: metaData
, completion: { (metadata, error) in
if let error = error {
completion(nil)
}
else{
storageRef.downloadURL { (url, error) in
guard let downloadURL = url else {
completion(nil)
return
}
completion(downloadURL)
}
print("success")
}
})
}
}catch let error {
print(error)
}
}
}
struct ImagePickerDelegate: UIViewControllerRepresentable {
let sourceType: UIImagePickerController.SourceType
let mediaTypes: [String]
let didPickVideo: (URL) -> Void
func makeUIViewController(context: Context) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.sourceType = sourceType
picker.mediaTypes = mediaTypes
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator(didPickVideo: didPickVideo)
}
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let didPickVideo: (URL) -> Void
init(didPickVideo: @escaping (URL) -> Void) {
self.didPickVideo = didPickVideo
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let videoURL = info[.mediaURL] as? URL {
didPickVideo(videoURL)
}
picker.dismiss(animated: true)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true)
}
}
}
struct VideoPlayerView: View {
var videoURL: URL
var body: some View {
VideoPlayer(player: AVPlayer(url: videoURL))
.onAppear {
// Auto-play the video when the view appears
let player = AVPlayer.shared()
player.play()
}
.onDisappear {
// Pause the video when the view disappears
let player = AVPlayer.shared()
player.pause()
}
}
}
extension AVPlayer {
static func shared() -> AVPlayer {
struct Singleton {
static let instance = AVPlayer()
}
return Singleton.instance
}
}
struct VideoPickerView_Previews: PreviewProvider {
static var previews: some View {
Homeview()
}
}

huangapple
  • 本文由 发表于 2023年5月10日 15:25:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76215896.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定