chore: atualização geral
This commit is contained in:
@@ -105,25 +105,64 @@ struct ModelDownloadView: View {
|
||||
.font(.caption)
|
||||
.foregroundStyle(catalog?.diarization == true ? Color.secondary : Color.orange)
|
||||
}
|
||||
SecureField("Token HuggingFace (diarização)", text: $hfTokenText)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.help("Token com acesso aos modelos gated pyannote (segmentation + speaker-diarization)")
|
||||
tokenField
|
||||
HStack {
|
||||
TextField("Nº de participantes (vazio = automático)", text: $numSpeakersText)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
Button("Salvar") { saveDiarization() }
|
||||
.disabled(isLoading)
|
||||
}
|
||||
setupSteps
|
||||
}
|
||||
} header: {
|
||||
Text("Diarização (participantes)")
|
||||
} footer: {
|
||||
Text("Opcional. Sem token, cada fala é atribuída a um único participante padrão.")
|
||||
Text("Opcional. Sem token, cada fala é atribuída a um único participante padrão. O token só é usado para baixar o modelo uma vez — depois disso a análise roda offline, nesta máquina.")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
/// Campo do token. Quando já existe um salvo, mostra o estado em vez de um
|
||||
/// campo vazio ambíguo — e oferece a remoção, já que salvar vazio não apaga.
|
||||
@ViewBuilder
|
||||
private var tokenField: some View {
|
||||
if catalog?.hfTokenSet == true {
|
||||
HStack {
|
||||
Label("Token salvo nesta máquina", systemImage: "key.fill")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
Spacer()
|
||||
Button("Remover") { removeToken() }
|
||||
.buttonStyle(.link)
|
||||
.disabled(isLoading)
|
||||
}
|
||||
}
|
||||
SecureField(
|
||||
catalog?.hfTokenSet == true ? "Substituir token…" : "Token HuggingFace (diarização)",
|
||||
text: $hfTokenText
|
||||
)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
.help("Token com acesso aos modelos gated pyannote (segmentation + speaker-diarization)")
|
||||
}
|
||||
|
||||
/// O token sozinho não basta: os dois modelos pyannote são "gated" e exigem
|
||||
/// aceitar os termos na conta antes do download funcionar.
|
||||
private var setupSteps: some View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
Text("Para ativar, uma vez só:")
|
||||
.font(.caption).bold()
|
||||
.foregroundStyle(.secondary)
|
||||
Link("1. Aceitar os termos do modelo de segmentação",
|
||||
destination: URL(string: "https://huggingface.co/pyannote/segmentation-3.0")!)
|
||||
Link("2. Aceitar os termos do modelo de diarização",
|
||||
destination: URL(string: "https://huggingface.co/pyannote/speaker-diarization-3.1")!)
|
||||
Link("3. Criar um token de acesso e colar acima",
|
||||
destination: URL(string: "https://huggingface.co/settings/tokens")!)
|
||||
}
|
||||
.font(.caption)
|
||||
}
|
||||
|
||||
private func saveDiarization() {
|
||||
var args: [String: Any] = ["num_speakers": numSpeakersText]
|
||||
if !hfTokenText.isEmpty {
|
||||
@@ -138,6 +177,15 @@ struct ModelDownloadView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func removeToken() {
|
||||
PythonBridge.call(command: "set_diarization", arguments: ["token": ""]) { _, _ in
|
||||
DispatchQueue.main.async {
|
||||
hfTokenText = ""
|
||||
Task { await refresh() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Storage
|
||||
|
||||
private var storageSection: some View {
|
||||
|
||||
Reference in New Issue
Block a user