[CmdletBinding()] param( [string]$RtcAppId = "6a8f92ca43726c017d34cce1", [switch]$EnableArkSummary, [string]$ArkContentModel = "", [switch]$Force ) $ErrorActionPreference = "Stop" $scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path $runtimeDirectory = Join-Path $scriptDirectory "runtime" $utf8NoBom = [System.Text.UTF8Encoding]::new($false) function Read-RequiredText { param([string]$Prompt, [string]$Default = "") $suffix = if ($Default) { " [$Default]" } else { "" } $value = Read-Host "$Prompt$suffix" if ([string]::IsNullOrWhiteSpace($value)) { $value = $Default } if ([string]::IsNullOrWhiteSpace($value)) { throw "$Prompt 不能为空" } return $value.Trim() } function Read-RequiredSecret { param([string]$Prompt, [int]$MinimumLength = 1) $secureValue = Read-Host $Prompt -AsSecureString $pointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureValue) try { $value = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($pointer) } finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($pointer) } if ($value.Length -lt $MinimumLength) { throw "$Prompt 长度不足" } return $value } function Write-SecretFile { param([string]$Name, [string]$Value) $target = Join-Path $runtimeDirectory $Name [IO.File]::WriteAllText($target, $Value, $utf8NoBom) } if ($RtcAppId.Length -ne 24) { throw "RTC AppId 必须正好为 24 个字符" } if ((Test-Path -LiteralPath $runtimeDirectory) -and -not $Force) { throw "本地凭据目录已经存在。确认需要重新配置后使用 -Force。" } New-Item -ItemType Directory -Path $runtimeDirectory -Force | Out-Null Write-Host "`n配置只保存在本机 deploy/local-rtc/runtime,已被 Git 忽略。" -ForegroundColor Cyan Write-Host "输入密钥时屏幕不会显示字符。`n" -ForegroundColor DarkGray $rtcAppKey = Read-RequiredSecret "RTC AppKey" 16 $volcAccessKeyId = Read-RequiredText "火山引擎 AccessKey ID" $volcSecretAccessKey = Read-RequiredSecret "火山引擎 Secret AccessKey" $doubaoAppId = Read-RequiredText "豆包端到端语音 APP ID" $doubaoAccessToken = Read-RequiredSecret "豆包端到端语音 Access Token" $speaker = Read-RequiredText "豆包音色 ID" "zh_female_vv_jupiter_bigtts" $arkApiKey = "" if ($EnableArkSummary) { $arkApiKey = Read-RequiredSecret "方舟 API Key" $ArkContentModel = Read-RequiredText "方舟内容模型 Endpoint ID" $ArkContentModel } $template = [ordered]@{ schema_version = "voice-chat-template-bundle-v1" templates = [ordered]@{ s2s_hybrid = [ordered]@{ AgentConfig = [ordered]@{ TargetUserId = @() UserId = "" WelcomeMessage = "" EnableConversationStateCallback = $false } Config = [ordered]@{ InterruptMode = 0 S2SConfig = [ordered]@{ Provider = "volcano" OutputMode = 0 ProviderParams = [ordered]@{ app = [ordered]@{ appid = $doubaoAppId token = $doubaoAccessToken } dialog = [ordered]@{ extra = [ordered]@{ model = "O" strict_audit = $true audit_response = "抱歉,这个话题我暂时无法回答。我们换个轻松的话题吧。" } } asr = [ordered]@{ extra = [ordered]@{ end_smooth_window_ms = 1200 } } tts = [ordered]@{ speaker = $speaker } } } } } } } Write-SecretFile "rtc-app-key" $rtcAppKey Write-SecretFile "volc-access-key-id" $volcAccessKeyId Write-SecretFile "volc-secret-access-key" $volcSecretAccessKey Write-SecretFile "ark-api-key" $arkApiKey [IO.File]::WriteAllText( (Join-Path $runtimeDirectory "voice-chat-template.json"), ($template | ConvertTo-Json -Depth 20), $utf8NoBom ) [IO.File]::WriteAllText( (Join-Path $runtimeDirectory "local-rtc.env"), "RTC_APP_ID=$RtcAppId`nCONTENT_GENERATOR=$(if ($EnableArkSummary) { 'ark' } else { 'local' })`nARK_CONTENT_MODEL=$ArkContentModel`n", $utf8NoBom ) Write-Host "`n本地真实 RTC 配置已生成。" -ForegroundColor Green Write-Host "下一步运行: .\deploy\local-rtc\start.ps1" -ForegroundColor Green