\n
Here's my ContentView
\nimport SwiftUI\nimport AVKit\n\nstruct ContentView: View {\n @ObservedObject var viewModel: ImmersiveVideoViewModel\n @Environment(\\.openImmersiveSpace) var openImmersiveSpace\n @Environment(\\.dismissImmersiveSpace) var dismissImmersiveSpace\n @State private var showVideoPlayer = false\n \n var body: some View {\n VStack {\n Toggle(viewModel.showImmersiveSpace ? "Back to Reality" : "Show Immersive space", isOn: $viewModel.showImmersiveSpace)\n .toggleStyle(.button)\n .onChange(of: viewModel.showImmersiveSpace) { _, newValue in\n Task {\n if newValue {\n if viewModel.videoType == .degree180 {\n showVideoPlayer = true\n } else {\n await openImmersiveSpace(id: "VideoImmersiveView")\n }\n } else {\n await dismissImmersiveSpace()\n }\n }\n }\n .controlSize(.extraLarge)\n \n Picker("Video Type", selection: $viewModel.videoType) {\n Text("360°").tag(VideoType.degree360)\n Text("180°").tag(VideoType.degree180)\n }\n .pickerStyle(SegmentedPickerStyle())\n .padding()\n }\n .fullScreenCover(isPresented: $showVideoPlayer) {\n if let playerViewController = viewModel.presentVideoPlayer() {\n VideoPlayerViewControllerRepresentable(playerViewController: playerViewController)\n }\n }\n }\n}\n\nstruct VideoPlayerViewControllerRepresentable: UIViewControllerRepresentable {\n let playerViewController: AVPlayerViewController\n \n func makeUIViewController(context: Context) -> AVPlayerViewController {\n return playerViewController\n }\n \n func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {}\n}\n
\nHere's my ImmersiveViewModel:
\nimport SwiftUI\nimport RealityKit\nimport AVKit\n\nenum VideoType {\n case degree360\n case degree180\n}\n\nclass ImmersiveVideoViewModel: ObservableObject {\n @Published var showImmersiveSpace = false\n @Published var videoType: VideoType = .degree360\n \n func generateVideoMaterial(for type: VideoType) -> VideoMaterial? {\n guard let url = Bundle.main.url(forResource: "SPATIAL", withExtension: "mov") else {\n print("Error loading video")\n return nil\n }\n \n self.videoType = type\n \n let avPlayer = AVPlayer(url: url)\n let videoMaterial = VideoMaterial(avPlayer: avPlayer)\n avPlayer.play()\n \n return videoMaterial\n }\n \n func presentVideoPlayer() -> AVPlayerViewController? {\n guard let url = Bundle.main.url(forResource: "SPATIAL", withExtension: "mov") else {\n print("Error loading video")\n return nil\n }\n \n let avPlayer = AVPlayer(url: url)\n let playerViewController = AVPlayerViewController()\n playerViewController.player = avPlayer\n \n avPlayer.play()\n \n return playerViewController\n }\n}\n
\nHere's the result of the code:
\n\n\n\n","author":{"@type":"Person","name":"Lahfir"},"upvoteCount":1,"answerCount":0,"acceptedAnswer":null}}Note: The video opened using Files is the same as the video that I loaded on my code!
\n
Reputation: 379
I'm trying to build a player to view spatial videos. When I try to open the video normally from Files or Photos in my VisionPro simulator, the View Immersive option is showing and the spatial video is representable. But I cannot view the same option in the player I build using AVPlayer
Here's my ContentView
import SwiftUI
import AVKit
struct ContentView: View {
@ObservedObject var viewModel: ImmersiveVideoViewModel
@Environment(\.openImmersiveSpace) var openImmersiveSpace
@Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace
@State private var showVideoPlayer = false
var body: some View {
VStack {
Toggle(viewModel.showImmersiveSpace ? "Back to Reality" : "Show Immersive space", isOn: $viewModel.showImmersiveSpace)
.toggleStyle(.button)
.onChange(of: viewModel.showImmersiveSpace) { _, newValue in
Task {
if newValue {
if viewModel.videoType == .degree180 {
showVideoPlayer = true
} else {
await openImmersiveSpace(id: "VideoImmersiveView")
}
} else {
await dismissImmersiveSpace()
}
}
}
.controlSize(.extraLarge)
Picker("Video Type", selection: $viewModel.videoType) {
Text("360°").tag(VideoType.degree360)
Text("180°").tag(VideoType.degree180)
}
.pickerStyle(SegmentedPickerStyle())
.padding()
}
.fullScreenCover(isPresented: $showVideoPlayer) {
if let playerViewController = viewModel.presentVideoPlayer() {
VideoPlayerViewControllerRepresentable(playerViewController: playerViewController)
}
}
}
}
struct VideoPlayerViewControllerRepresentable: UIViewControllerRepresentable {
let playerViewController: AVPlayerViewController
func makeUIViewController(context: Context) -> AVPlayerViewController {
return playerViewController
}
func updateUIViewController(_ uiViewController: AVPlayerViewController, context: Context) {}
}
Here's my ImmersiveViewModel:
import SwiftUI
import RealityKit
import AVKit
enum VideoType {
case degree360
case degree180
}
class ImmersiveVideoViewModel: ObservableObject {
@Published var showImmersiveSpace = false
@Published var videoType: VideoType = .degree360
func generateVideoMaterial(for type: VideoType) -> VideoMaterial? {
guard let url = Bundle.main.url(forResource: "SPATIAL", withExtension: "mov") else {
print("Error loading video")
return nil
}
self.videoType = type
let avPlayer = AVPlayer(url: url)
let videoMaterial = VideoMaterial(avPlayer: avPlayer)
avPlayer.play()
return videoMaterial
}
func presentVideoPlayer() -> AVPlayerViewController? {
guard let url = Bundle.main.url(forResource: "SPATIAL", withExtension: "mov") else {
print("Error loading video")
return nil
}
let avPlayer = AVPlayer(url: url)
let playerViewController = AVPlayerViewController()
playerViewController.player = avPlayer
avPlayer.play()
return playerViewController
}
}
Here's the result of the code:
Note: The video opened using Files is the same as the video that I loaded on my code!
Upvotes: 1
Views: 113