Skip to content

Commit

Permalink
Use fileCDN with video attachments
Browse files Browse the repository at this point in the history
  • Loading branch information
bpollman committed Oct 20, 2024
1 parent 6c5cfeb commit 00fd3b6
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 35 deletions.
40 changes: 30 additions & 10 deletions Sources/StreamChatSwiftUI/ChatChannel/Gallery/GalleryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,20 +153,40 @@ public struct GalleryView: View {
}

struct StreamVideoPlayer: View {

@State var player: AVPlayer


@Injected(\.utils) private var utils

private var fileCDN: FileCDN {
utils.fileCDN
}

let url: URL

@State var avPlayer: AVPlayer?
@State var error: Error?

init(url: URL) {
let player = AVPlayer(url: url)
_player = State(wrappedValue: player)
self.url = url
}

var body: some View {
VideoPlayer(player: player)
.clipped()
.onAppear {
try? AVAudioSession.sharedInstance().setCategory(.playback, options: [])
player.play()
VStack {
if let avPlayer {
VideoPlayer(player: avPlayer)
.clipped()
}
}
.onAppear {
fileCDN.adjustedURL(for: url) { result in
switch result {
case let .success(url):
self.avPlayer = AVPlayer(url: url)
try? AVAudioSession.sharedInstance().setCategory(.playback, options: [])
self.avPlayer?.play()
case let .failure(error):
self.error = error
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@ public struct VideoPlayerView: View {

@Injected(\.fonts) private var fonts
@Injected(\.colors) private var colors
@Injected(\.utils) private var utils

private var fileCDN: FileCDN {
utils.fileCDN
}

let attachment: ChatMessageVideoAttachment
let author: ChatUser
@Binding var isShown: Bool

private let avPlayer: AVPlayer
@State private var avPlayer: AVPlayer?
@State private var error: Error?

public init(
attachment: ChatMessageVideoAttachment,
Expand All @@ -26,7 +32,6 @@ public struct VideoPlayerView: View {
) {
self.attachment = attachment
self.author = author
avPlayer = AVPlayer(url: attachment.payload.videoURL)
_isShown = isShown
}

Expand All @@ -37,7 +42,9 @@ public struct VideoPlayerView: View {
subtitle: author.onlineText,
isShown: $isShown
)
VideoPlayer(player: avPlayer)
if let avPlayer {
VideoPlayer(player: avPlayer)
}
Spacer()
HStack {
ShareButtonView(content: [attachment.payload.videoURL])
Expand All @@ -48,11 +55,19 @@ public struct VideoPlayerView: View {
.foregroundColor(Color(colors.text))
}
.onAppear {
try? AVAudioSession.sharedInstance().setCategory(.playback, options: [])
avPlayer.play()
fileCDN.adjustedURL(for: attachment.payload.videoURL) { result in
switch result {
case let .success(url):
self.avPlayer = AVPlayer(url: url)
try? AVAudioSession.sharedInstance().setCategory(.playback, options: [])
self.avPlayer?.play()
case let .failure(error):
self.error = error
}
}
}
.onDisappear {
avPlayer.replaceCurrentItem(with: nil)
avPlayer?.replaceCurrentItem(with: nil)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public struct FileAttachmentPreview: View {

var url: URL

@State var adjustedUrl: URL?
@State private var adjustedUrl: URL?
@State private var isLoading = false
@State private var title: String?
@State private var error: Error?
Expand Down
2 changes: 1 addition & 1 deletion Sources/StreamChatSwiftUI/Utils/Common/FileCDN.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import Foundation
import StreamChat

/// A protocol the video preview uploader implementation must conform to.
/// FileCDN provides a set of functions to improve handling of files & videos from CDN.
public protocol FileCDN: AnyObject {
/// Prepare and return an adjusted or signed `URL` for the given file `URL`
/// This function can be used to intercept an unsigned URL and return a valid signed URL
Expand Down
48 changes: 31 additions & 17 deletions Sources/StreamChatSwiftUI/Utils/Common/VideoPreviewLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public protocol VideoPreviewLoader: AnyObject {

/// The `VideoPreviewLoader` implemenation used by default.
public final class DefaultVideoPreviewLoader: VideoPreviewLoader {
@Injected(\.utils) var utils

private let cache: Cache<URL, UIImage>

public init(countLimit: Int = 50) {
Expand All @@ -39,26 +41,38 @@ public final class DefaultVideoPreviewLoader: VideoPreviewLoader {
return call(completion, with: .success(cached))
}

let asset = AVURLAsset(url: url)
let imageGenerator = AVAssetImageGenerator(asset: asset)
let frameTime = CMTime(seconds: 0.1, preferredTimescale: 600)

imageGenerator.appliesPreferredTrackTransform = true
imageGenerator.generateCGImagesAsynchronously(forTimes: [.init(time: frameTime)]) { [weak self] _, image, _, _, error in
guard let self = self else { return }

let result: Result<UIImage, Error>
if let thumbnail = image {
result = .success(.init(cgImage: thumbnail))
} else if let error = error {
result = .failure(error)
} else {
log.error("Both error and image are `nil`.")
utils.fileCDN.adjustedURL(for: url) { result in

let adjustedUrl: URL
switch result {
case let .success(url):
adjustedUrl = url
case let .failure(error):
self.call(completion, with: .failure(error))
return
}

self.cache[url] = try? result.get()
self.call(completion, with: result)
let asset = AVURLAsset(url: adjustedUrl)
let imageGenerator = AVAssetImageGenerator(asset: asset)
let frameTime = CMTime(seconds: 0.1, preferredTimescale: 600)

imageGenerator.appliesPreferredTrackTransform = true
imageGenerator.generateCGImagesAsynchronously(forTimes: [.init(time: frameTime)]) { [weak self] _, image, _, _, error in
guard let self = self else { return }

let result: Result<UIImage, Error>
if let thumbnail = image {
result = .success(.init(cgImage: thumbnail))
} else if let error = error {
result = .failure(error)
} else {
log.error("Both error and image are `nil`.")
return
}

self.cache[url] = try? result.get()
self.call(completion, with: result)
}
}
}

Expand Down

0 comments on commit 00fd3b6

Please sign in to comment.