|
1 | 1 | import SwiftUI |
2 | 2 | import AVFoundation |
| 3 | +import Foundation |
3 | 4 |
|
4 | 5 | struct ContentView: View { |
5 | 6 | @StateObject var whisperState = WhisperState() |
@@ -29,15 +30,125 @@ struct ContentView: View { |
29 | 30 | Text(verbatim: whisperState.messageLog) |
30 | 31 | .frame(maxWidth: .infinity, alignment: .leading) |
31 | 32 | } |
| 33 | + .font(.footnote) |
| 34 | + .padding() |
| 35 | + .background(Color.gray.opacity(0.1)) |
| 36 | + .cornerRadius(10) |
| 37 | + |
| 38 | + HStack { |
| 39 | + Button("Clear Logs", action: { |
| 40 | + whisperState.messageLog = "" |
| 41 | + }) |
| 42 | + .font(.footnote) |
| 43 | + .buttonStyle(.bordered) |
| 44 | + |
| 45 | + Button("Copy Logs", action: { |
| 46 | + UIPasteboard.general.string = whisperState.messageLog |
| 47 | + }) |
| 48 | + .font(.footnote) |
| 49 | + .buttonStyle(.bordered) |
| 50 | + |
| 51 | + Button("Bench", action: { |
| 52 | + Task { |
| 53 | + await whisperState.benchCurrentModel() |
| 54 | + } |
| 55 | + }) |
| 56 | + .font(.footnote) |
| 57 | + .buttonStyle(.bordered) |
| 58 | + .disabled(!whisperState.canTranscribe) |
| 59 | + |
| 60 | + Button("Bench All", action: { |
| 61 | + Task { |
| 62 | + await whisperState.bench(models: ModelsView.getDownloadedModels()) |
| 63 | + } |
| 64 | + }) |
| 65 | + .font(.footnote) |
| 66 | + .buttonStyle(.bordered) |
| 67 | + .disabled(!whisperState.canTranscribe) |
| 68 | + } |
| 69 | + |
| 70 | + NavigationLink(destination: ModelsView(whisperState: whisperState)) { |
| 71 | + Text("View Models") |
| 72 | + } |
| 73 | + .font(.footnote) |
| 74 | + .padding() |
32 | 75 | } |
33 | 76 | .navigationTitle("Whisper SwiftUI Demo") |
34 | 77 | .padding() |
35 | 78 | } |
36 | 79 | } |
37 | | -} |
38 | 80 |
|
39 | | -struct ContentView_Previews: PreviewProvider { |
40 | | - static var previews: some View { |
41 | | - ContentView() |
| 81 | + struct ModelsView: View { |
| 82 | + @ObservedObject var whisperState: WhisperState |
| 83 | + @Environment(\.dismiss) var dismiss |
| 84 | + |
| 85 | + private static let models: [Model] = [ |
| 86 | + Model(name: "tiny", info: "(F16, 75 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.bin", filename: "tiny.bin"), |
| 87 | + Model(name: "tiny-q5_1", info: "(31 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny-q5_1.bin", filename: "tiny-q5_1.bin"), |
| 88 | + Model(name: "tiny-q8_0", info: "(42 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny-q8_0.bin", filename: "tiny-q8_0.bin"), |
| 89 | + Model(name: "tiny.en", info: "(F16, 75 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en.bin", filename: "tiny.en.bin"), |
| 90 | + Model(name: "tiny.en-q5_1", info: "(31 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en-q5_1.bin", filename: "tiny.en-q5_1.bin"), |
| 91 | + Model(name: "tiny.en-q8_0", info: "(42 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.en-q8_0.bin", filename: "tiny.en-q8_0.bin"), |
| 92 | + Model(name: "base", info: "(F16, 142 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.bin", filename: "base.bin"), |
| 93 | + Model(name: "base-q5_1", info: "(57 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base-q5_1.bin", filename: "base-q5_1.bin"), |
| 94 | + Model(name: "base-q8_0", info: "(78 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base-q8_0.bin", filename: "base-q8_0.bin"), |
| 95 | + Model(name: "base.en", info: "(F16, 142 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en.bin", filename: "base.en.bin"), |
| 96 | + Model(name: "base.en-q5_1", info: "(57 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en-q5_1.bin", filename: "base.en-q5_1.bin"), |
| 97 | + Model(name: "base.en-q8_0", info: "(78 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.en-q8_0.bin", filename: "base.en-q8_0.bin"), |
| 98 | + Model(name: "small", info: "(F16, 466 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin", filename: "small.bin"), |
| 99 | + Model(name: "small-q5_1", info: "(181 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small-q5_1.bin", filename: "small-q5_1.bin"), |
| 100 | + Model(name: "small-q8_0", info: "(252 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small-q8_0.bin", filename: "small-q8_0.bin"), |
| 101 | + Model(name: "small.en", info: "(F16, 466 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.en.bin", filename: "small.en.bin"), |
| 102 | + Model(name: "small.en-q5_1", info: "(181 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.en-q5_1.bin", filename: "small.en-q5_1.bin"), |
| 103 | + Model(name: "small.en-q8_0", info: "(252 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.en-q8_0.bin", filename: "small.en-q8_0.bin"), |
| 104 | + Model(name: "medium", info: "(F16, 1.5 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.bin", filename: "medium.bin"), |
| 105 | + Model(name: "medium-q5_0", info: "(514 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium-q5_0.bin", filename: "medium-q5_0.bin"), |
| 106 | + Model(name: "medium-q8_0", info: "(785 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium-q8_0.bin", filename: "medium-q8_0.bin"), |
| 107 | + Model(name: "medium.en", info: "(F16, 1.5 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.en.bin", filename: "medium.en.bin"), |
| 108 | + Model(name: "medium.en-q5_0", info: "(514 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.en-q5_0.bin", filename: "medium.en-q5_0.bin"), |
| 109 | + Model(name: "medium.en-q8_0", info: "(785 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-medium.en-q8_0.bin", filename: "medium.en-q8_0.bin"), |
| 110 | + Model(name: "large-v1", info: "(F16, 2.9 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large.bin", filename: "large.bin"), |
| 111 | + Model(name: "large-v2", info: "(F16, 2.9 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v2.bin", filename: "large-v2.bin"), |
| 112 | + Model(name: "large-v2-q5_0", info: "(1.1 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v2-q5_0.bin", filename: "large-v2-q5_0.bin"), |
| 113 | + Model(name: "large-v2-q8_0", info: "(1.5 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v2-q8_0.bin", filename: "large-v2-q8_0.bin"), |
| 114 | + Model(name: "large-v3", info: "(F16, 2.9 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3.bin", filename: "large-v3.bin"), |
| 115 | + Model(name: "large-v3-q5_0", info: "(1.1 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-q5_0.bin", filename: "large-v3-q5_0.bin"), |
| 116 | + Model(name: "large-v3-turbo", info: "(F16, 1.5 GiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin", filename: "large-v3-turbo.bin"), |
| 117 | + Model(name: "large-v3-turbo-q5_0", info: "(547 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo-q5_0.bin", filename: "large-v3-turbo-q5_0.bin"), |
| 118 | + Model(name: "large-v3-turbo-q8_0", info: "(834 MiB)", url: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo-q8_0.bin", filename: "large-v3-turbo-q8_0.bin"), |
| 119 | + ] |
| 120 | + |
| 121 | + static func getDownloadedModels() -> [Model] { |
| 122 | + // Filter models that have been downloaded |
| 123 | + return models.filter { |
| 124 | + FileManager.default.fileExists(atPath: $0.fileURL.path()) |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + func loadModel(model: Model) { |
| 129 | + Task { |
| 130 | + dismiss() |
| 131 | + whisperState.loadModel(path: model.fileURL) |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + var body: some View { |
| 136 | + List { |
| 137 | + Section(header: Text("Models")) { |
| 138 | + ForEach(ModelsView.models) { model in |
| 139 | + DownloadButton(model: model) |
| 140 | + .onLoad(perform: loadModel) |
| 141 | + } |
| 142 | + } |
| 143 | + } |
| 144 | + .listStyle(GroupedListStyle()) |
| 145 | + .navigationBarTitle("Models", displayMode: .inline).toolbar {} |
| 146 | + } |
42 | 147 | } |
43 | 148 | } |
| 149 | + |
| 150 | +//struct ContentView_Previews: PreviewProvider { |
| 151 | +// static var previews: some View { |
| 152 | +// ContentView() |
| 153 | +// } |
| 154 | +//} |
0 commit comments