Let us rewrite this app, please give me ios 17 compatible code to run on device on my A17pro chip on iphone 15 pro. The app should compile without errors and warning and then run properly.

//ContentView.swift
import SwiftUI

struct ContentView: View {
    @State private var audioURL: URL?
    @State private var transcriptionStatus: String = "Please select an audio file."
    @State private var isProcessing: Bool = false
    @State private var showFilePicker: Bool = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Subtitle Video Generator")
                .font(.largeTitle)
                .padding()

            Text(transcriptionStatus)
                .padding()
                .multilineTextAlignment(.center)

            Button(action: {
                showFilePicker = true
            }) {
                Text("Select Audio File")
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .padding()
                    .background(isProcessing ? Color.gray : Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
            .disabled(isProcessing)
            .padding(.horizontal)
            .fileImporter(
                isPresented: $showFilePicker,
                allowedContentTypes: [.audio],
                allowsMultipleSelection: false
            ) { result in
                do {
                    if let selectedFileURL = try result.get().first {
                        if selectedFileURL.startAccessingSecurityScopedResource() {
                            defer { selectedFileURL.stopAccessingSecurityScopedResource() }

                            // Copy the file into the app's documents directory
                            let fileManager = FileManager.default
                            let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
                            let destinationURL = documentsURL.appendingPathComponent(selectedFileURL.lastPathComponent)

                            // Remove existing file if it exists
                            if fileManager.fileExists(atPath: destinationURL.path) {
                                try fileManager.removeItem(at: destinationURL)
                            }

                            try fileManager.copyItem(at: selectedFileURL, to: destinationURL)

                            // Update the audioURL to point to the copied file
                            audioURL = destinationURL
                            transcriptionStatus = "Selected file: (selectedFileURL.lastPathComponent)"
                        } else {
                            transcriptionStatus = "Failed to access file due to security restrictions."
                            print("Could not access security-scoped resource.")
                        }
                    }
                } catch {
                    transcriptionStatus = "Failed to select file."
                    print("File selection error: (error.localizedDescription)")
                }
            }

            Button(action: {
                startProcessing()
            }) {
                Text("Generate Subtitle Video")
                    .frame(minWidth: 0, maxWidth: .infinity)
                    .padding()
                    .background((audioURL == nil || isProcessing) ? Color.gray : Color.green)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
            .disabled(audioURL == nil || isProcessing)
            .padding(.horizontal)
        }
    }

    func startProcessing() {
        guard let audioURL = audioURL else { return }
        isProcessing = true
        transcriptionStatus = "Transcribing audio..."

        // Perform speech recognition and video generation
        SpeechProcessor.shared.transcribeAudio(url: audioURL) { result in
            switch result {
            case .success(let words):
                transcriptionStatus = "Generating video..."
                VideoGenerator.shared.generateVideo(with: words, audioURL: audioURL) { success in
                    DispatchQueue.main.async {
                        isProcessing = false
                        if success {
                            transcriptionStatus = "Video generated successfully! Check your Photos app."
                        } else {
                            transcriptionStatus = "Failed to generate video."
                        }
                    }
                }
            case .failure(_):
                DispatchQueue.main.async {
                    isProcessing = false
                    transcriptionStatus = "Transcription failed: (error.localizedDescription)"
                }
            }
        }
    }
}

//
//  SpeechProcessor.swift
import Foundation
import Speech

class SpeechProcessor {
    static let shared = SpeechProcessor()
    private let speechRecognizer: SFSpeechRecognizer?
    
    private init() {
        // Initialize speech recognizer for English (United States)
        if let englishRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US")), englishRecognizer.isAvailable {
            speechRecognizer = englishRecognizer
        } else {
            speechRecognizer = nil
            print("Speech recognition not available for English (en-US).")
        }
    }

    func transcribeAudio(url: URL, completion: @escaping (Result<[TranscribedWord], Error>) -> Void) {
        guard let recognizer = speechRecognizer, recognizer.isAvailable else {
            completion(.failure(NSError(domain: "SpeechProcessor", code: -1, userInfo: [NSLocalizedDescriptionKey: "Speech recognizer not available."])))
            return
        }

        let request = SFSpeechURLRecognitionRequest(url: url)
        // Comment out or set to false to allow both on-device and online recognition
        // request.requiresOnDeviceRecognition = true

        recognizer.recognitionTask(with: request) { result, error in
            if let error = error {
                print("Speech recognition error: (error.localizedDescription)")
                completion(.failure(error))
                return
            }

            guard let result = result else {
                print("No recognition result.")
                completion(.failure(NSError(domain: "SpeechProcessor", code: -1, userInfo: [NSLocalizedDescriptionKey: "No recognition result."])))
                return
            }

            if result.isFinal {
                // Extract words with timing information
                let words = self.extractWords(from: result)
                completion(.success(words))
            }
        }
    }

    private func extractWords(from result: SFSpeechRecognitionResult) -> [TranscribedWord] {
        var words: [TranscribedWord] = []
        for segment in result.bestTranscription.segments {
            let word = TranscribedWord(
                text: segment.substring,
                startTime: segment.timestamp,
                duration: segment.duration
            )
            words.append(word)
        }
        return words
    }
}

struct TranscribedWord {
    let text: String
    let startTime: TimeInterval
    let duration: TimeInterval
}


//
//  VideoGenerator.swift
import Foundation
import AVFoundation
import UIKit
import Photos

class VideoGenerator {
    static let shared = VideoGenerator()
    
    func generateVideo(with words: [TranscribedWord], audioURL: URL, completion: @escaping (Bool) -> Void) {
        // Run the async task
        Task {
            let success = await self.generateVideoAsync(with: words, audioURL: audioURL)
            DispatchQueue.main.async {
                completion(success)
            }
        }
    }
    
    private func generateVideoAsync(with words: [TranscribedWord], audioURL: URL) async -> Bool {
        // Video settings
        let videoSize = CGSize(width: 1280, height: 720)
        let fps: Int32 = 30
        
        // Calculate total duration
        guard let lastWord = words.last else {
            print("No words to process.")
            return false
        }
        let duration = lastWord.startTime + lastWord.duration
        
        // Create an AVMutableComposition
        let composition = AVMutableComposition()
        
        // Load audio asset properties asynchronously
        let audioAsset = AVURLAsset(url: audioURL)
        
        // Load the duration and tracks, capturing the results
        let audioDuration: CMTime
        let audioTracks: [AVAssetTrack]
        
        do {
            audioDuration = try await audioAsset.load(.duration)
            audioTracks = try await audioAsset.loadTracks(withMediaType: .audio)
        } catch {
            print("Failed to load audio asset properties: (error.localizedDescription)")
            return false
        }
        
        guard let audioTrack = audioTracks.first else {
            print("No audio tracks available.")
            return false
        }
        
        let audioCompositionTrack = composition.addMutableTrack(
            withMediaType: .audio,
            preferredTrackID: kCMPersistentTrackID_Invalid
        )
        
        do {
            try audioCompositionTrack?.insertTimeRange(
                CMTimeRange(start: .zero, duration: audioDuration),
                of: audioTrack,
                at: .zero
            )
        } catch {
            print("Failed to insert audio track: (error.localizedDescription)")
            return false
        }
        
        // Video composition
        let videoComposition = AVMutableVideoComposition()
        videoComposition.renderSize = videoSize
        videoComposition.frameDuration = CMTime(value: 1, timescale: fps)
        
        // Instruction
        let instruction = AVMutableVideoCompositionInstruction()
        instruction.timeRange = CMTimeRange(start: .zero, duration: CMTime(seconds: duration, preferredTimescale: fps))
        videoComposition.instructions = [instruction]
        
        // Layers
        let parentLayer = CALayer()
        parentLayer.frame = CGRect(origin: .zero, size: videoSize)
        let videoLayer = CALayer()
        videoLayer.frame = CGRect(origin: .zero, size: videoSize)
        parentLayer.addSublayer(videoLayer)
        
        // Add text layer
        let textLayer = createTextLayer(words: words, videoSize: videoSize)
        parentLayer.addSublayer(textLayer)
        
        // Set animation tool
        videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(
            postProcessingAsVideoLayer: videoLayer,
            in: parentLayer
        )
        
        // Export the video
        let isExported = await exportVideo(
            composition: composition,
            videoComposition: videoComposition,
            outputURL: FileManager.default.temporaryDirectory.appendingPathComponent("SubtitleVideo.mov")
        )
        
        return isExported
    }
    
    private func exportVideo(composition: AVMutableComposition, videoComposition: AVMutableVideoComposition, outputURL: URL) async -> Bool {
        // Export settings
        guard let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else {
            print("Failed to create exporter.")
            return false
        }
        
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let outputURL = documentsURL.appendingPathComponent("SubtitleVideo.mov")
        try? FileManager.default.removeItem(at: outputURL)
        exporter.outputURL = outputURL
        exporter.outputFileType = .mov
        exporter.shouldOptimizeForNetworkUse = true
        exporter.videoComposition = videoComposition
        
        // Export asynchronously using withCheckedContinuation
            return await withCheckedContinuation { continuation in
                exporter.exportAsynchronously {
                    DispatchQueue.main.async {
                        switch exporter.status {
                        case .completed:
                            // Save to Photos or notify success
                            print("Video exported to Documents directory.")
                            continuation.resume(returning: true)
                        case .failed:
                            if let error = exporter.error {
                                print("Export failed: (error.localizedDescription) ((error))")
                            } else {
                                print("Export failed: Unknown error")
                            }
                            continuation.resume(returning: false)
                        case .cancelled:
                            print("Export cancelled.")
                            continuation.resume(returning: false)
                        default:
                            print("Export completed with status: (exporter.status)")
                            continuation.resume(returning: false)
                        }
                    }
            }
        }
    }
    
    private func saveVideoToPhotos(outputURL: URL, completion: @escaping (Bool) -> Void) {
        PHPhotoLibrary.requestAuthorization(for: .addOnly) { status in
            guard status == .authorized || status == .limited else {
                print("Photo library access denied.")
                completion(false)
                return
            }
            
            PHPhotoLibrary.shared().performChanges({
                PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: outputURL)
            }) { saved, error in
                if saved {
                    print("Video saved to Photos.")
                    completion(true)
                } else {
                    print("Failed to save video to Photos")
                    completion(false)
                }
            }
        }
    }
    
    private func createTextLayer(words: [TranscribedWord], videoSize: CGSize) -> CALayer {
        let parentLayer = CALayer()
        parentLayer.frame = CGRect(origin: .zero, size: videoSize)
        
        // Disable accessibility for the parent layer
        parentLayer.isAccessibilityElement = false
        parentLayer.accessibilityElementsHidden = true
        
        let fontSize: CGFloat = 48
        let font = UIFont.systemFont(ofSize: fontSize)
        let normalColor = UIColor.gray.cgColor
        let highlightedColor = UIColor.red.cgColor
        let highlightedBackgroundColor = UIColor.white.cgColor
        
        // Starting positions
        var xPosition: CGFloat = 20
        var yPosition: CGFloat = videoSize.height / 2 - fontSize / 2
        
        // Maximum width before wrapping
        let maxWidth = videoSize.width - 40
        
        // Space between words
        let spaceWidth = " ".size(withAttributes: [.font: font]).width
        
        for word in words {
            // Create attributed string for the word
            let wordAttributes: [NSAttributedString.Key: Any] = [
                .font: font,
                .foregroundColor: UIColor.gray
            ]
            let wordAttributedString = NSAttributedString(string: word.text, attributes: wordAttributes)
            
            // Calculate word size
            let wordSize = wordAttributedString.size()
            
            // Wrap to next line if needed
            if xPosition + wordSize.width > maxWidth {
                xPosition = 20 // Reset to left margin
                yPosition += fontSize + 10 // Move down by font size plus padding
            }
            
            // Create a CATextLayer for the word
            let wordLayer = CATextLayer()
            wordLayer.string = wordAttributedString
            wordLayer.frame = CGRect(x: xPosition, y: yPosition, width: wordSize.width, height: wordSize.height)
            wordLayer.contentsScale = UIScreen.main.scale
            wordLayer.alignmentMode = .left
            wordLayer.backgroundColor = UIColor.clear.cgColor
            wordLayer.foregroundColor = normalColor
            
            // Disable accessibility for the word layer
            wordLayer.isAccessibilityElement = false
            wordLayer.accessibilityElementsHidden = true
            
            // Add the word layer to the parent layer
            parentLayer.addSublayer(wordLayer)
            
            // Animate foregroundColor and backgroundColor
            let colorAnimation = CABasicAnimation(keyPath: "foregroundColor")
            colorAnimation.fromValue = normalColor
            colorAnimation.toValue = highlightedColor
            colorAnimation.beginTime = AVCoreAnimationBeginTimeAtZero + word.startTime
            colorAnimation.duration = word.duration
            colorAnimation.fillMode = .forwards
            colorAnimation.isRemovedOnCompletion = false
            
            let backgroundAnimation = CABasicAnimation(keyPath: "backgroundColor")
            backgroundAnimation.fromValue = UIColor.clear.cgColor
            backgroundAnimation.toValue = highlightedBackgroundColor
            backgroundAnimation.beginTime = AVCoreAnimationBeginTimeAtZero + word.startTime
            backgroundAnimation.duration = word.duration
            backgroundAnimation.fillMode = .forwards
            backgroundAnimation.isRemovedOnCompletion = false
            
            // Group animations
            let animationGroup = CAAnimationGroup()
            animationGroup.animations = [colorAnimation, backgroundAnimation]
            animationGroup.duration = word.startTime + word.duration
            animationGroup.beginTime = AVCoreAnimationBeginTimeAtZero // Start at zero relative to the video timeline
            animationGroup.fillMode = .forwards
            animationGroup.isRemovedOnCompletion = false
            
            // Add the animation to the word layer
            wordLayer.add(animationGroup, forKey: "highlight")
            
            // Update xPosition for next word
            xPosition += wordSize.width + spaceWidth
        }
        
        return parentLayer
    }
}


//
//  subtitleApp.swift
import SwiftUI
import Speech

@main
struct subtitleApp:App {
    init() {
        requestSpeechAuthorization()
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }

    func requestSpeechAuthorization() {
        SFSpeechRecognizer.requestAuthorization { authStatus in
            switch authStatus {
            case .authorized:
                print("Speech recognition authorized.")
            case .denied:
                print("User denied access to speech recognition.")
            case .restricted:
                print("Speech recognition restricted.")
            case .notDetermined:
                print("Speech recognition not determined.")
            @unknown default:
                print("Unknown speech recognition authorization status.")
            }
        }
    }
}