Adding VTT subtitles to a streaming video from an URL

Hi,

I've started learning swiftUI a few months ago, and now I'm trying to build my first app :)

I am trying to display VTT subtitles from an external URL into a streaming video using AVPlayer and AVMutableComposition.

I have been trying for a few days, checking online and on Apple's documentation, but I can't manage to make it work. So far, I managed to display the subtitles, but there is no video or audio playing...

Could someone help?

Thanks in advance, I hope the code is not too confusing.

//  EpisodeDetailView.swift
//  OroroPlayer_v1
//
//  Created by Juan Valenzuela on 2023-11-25.
//

import AVKit
import SwiftUI

struct EpisodeDetailView4: View {
    @State private var episodeDetailVM = EpisodeDetailViewModel()
    let episodeID: Int
    @State private var player = AVPlayer()
    @State private var subs = AVPlayer()
    
    var body: some View {
        VideoPlayer(player: player)
            .ignoresSafeArea()
            .task {
                do {
                    try await episodeDetailVM.fetchEpisode(id: episodeID)
                    let episode = episodeDetailVM.episodeDetail
                    guard let videoURLString = episode.url else {
                        print("Invalid videoURL or missing data")
                        return
                    }
                    guard let subtitleURLString = episode.subtitles?[0].url else {
                        print("Invalid subtitleURLs or missing data")
                        return
                    }
                    let videoURL = URL(string: videoURLString)!
                    let subtitleURL = URL(string: subtitleURLString)!
                    
                    let videoAsset = AVURLAsset(url: videoURL)
                    let subtitleAsset = AVURLAsset(url: subtitleURL)
                    
                    
                    let movieWithSubs = AVMutableComposition()
                    
                    let videoTrack = movieWithSubs.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
                    let audioTrack = movieWithSubs.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
                    let subtitleTrack = movieWithSubs.addMutableTrack(withMediaType: .text, preferredTrackID: kCMPersistentTrackID_Invalid)
                    //
                    if let videoTrackItem = try await videoAsset.loadTracks(withMediaType: .video).first {
                        try await videoTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.load(.duration)),
                                                              of: videoTrackItem,
                                                              at: .zero)
                    }
                    
                    if let audioTrackItem = try await videoAsset.loadTracks(withMediaType: .audio).first {
                        try await audioTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.load(.duration)),
                                                              of: audioTrackItem,
                                                              at: .zero)
                    }
                    
                    if let subtitleTrackItem = try await subtitleAsset.loadTracks(withMediaType: .text).first {
                        try await subtitleTrack?.insertTimeRange(CMTimeRangeMake(start: .zero, duration: videoAsset.load(.duration)),
                                                                 of: subtitleTrackItem,
                                                                 at: .zero)
                    }
                    
                    let playerItem = AVPlayerItem(asset: movieWithSubs)
                    player = AVPlayer(playerItem: playerItem)
                    let playerController = AVPlayerViewController()
                    playerController.player = player
                    playerController.player?.play()
                    //                player.play()
                } catch {
                    print("Error: \(error.localizedDescription)")
                }
            }
    }
}

#Preview {
    EpisodeDetailView4(episodeID: 39288)
}