feat(voice): STT 统一到 X-Api-Key,与 TTS 共用同一 API Key
- transcribe_flash 新增 api_key 参数:新版 X-Api-Key 单头鉴权, 无则回退旧版 X-Api-App-Key / X-Api-Access-Key 双头 - stt_cmd 优先读 secrets.api_keys.volc_tts,appid/token 降为回退 - _get_tts_credentials 更名 _get_voice_credentials(TTS/STT 共用)
This commit is contained in:
@@ -49,8 +49,8 @@ skill 或其他脚本应通过上述命令定位资源,避免硬编码 `~/work
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
mytoolkit env set secrets.api_keys.ark <key>
|
mytoolkit env set secrets.api_keys.ark <key>
|
||||||
mytoolkit env set secrets.api_keys.volc_tts <api_key> # TTS 新版 API Key(X-Api-Key)
|
mytoolkit env set secrets.api_keys.volc_tts <api_key> # TTS/STT 新版 API Key(X-Api-Key,推荐)
|
||||||
mytoolkit env set secrets.volcengine.app_id <appid> # STT 旧版应用凭证
|
mytoolkit env set secrets.volcengine.app_id <appid> # 旧版应用凭证(回退用)
|
||||||
mytoolkit env set secrets.volcengine.access_token <token>
|
mytoolkit env set secrets.volcengine.access_token <token>
|
||||||
mytoolkit env list # 查看所有 key
|
mytoolkit env list # 查看所有 key
|
||||||
mytoolkit env export # 导出为 shell export 语句
|
mytoolkit env export # 导出为 shell export 语句
|
||||||
@@ -80,7 +80,7 @@ mytoolkit voice tts "文本" -v zh_female_xiaohe_uranus_bigtts --format mp3 --sp
|
|||||||
|
|
||||||
### 语音识别 (STT)
|
### 语音识别 (STT)
|
||||||
|
|
||||||
豆包录音文件识别极速版(flash ASR),STT 仍用旧版 `secrets.volcengine.app_id` / `access_token`(TTS 已改用 `secrets.api_keys.volc_tts`):
|
豆包录音文件识别极速版(flash ASR),STT 优先用新版 **API Key**(`secrets.api_keys.volc_tts`,`X-Api-Key` 鉴权,与 TTS 同一个 key),旧版 `secrets.volcengine.app_id` / `access_token` 仅作回退:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
mytoolkit voice stt -i clip.webm
|
mytoolkit voice stt -i clip.webm
|
||||||
|
|||||||
+13
-4
@@ -126,13 +126,19 @@ def transcribe_flash(
|
|||||||
token: str,
|
token: str,
|
||||||
audio_path: str | Path,
|
audio_path: str | Path,
|
||||||
*,
|
*,
|
||||||
|
api_key: str | None = None,
|
||||||
uid: str | None = None,
|
uid: str | None = None,
|
||||||
timeout_sec: float = 60.0,
|
timeout_sec: float = 60.0,
|
||||||
hotwords: Sequence[str] | None = None,
|
hotwords: Sequence[str] | None = None,
|
||||||
history: Sequence[str] | None = None,
|
history: Sequence[str] | None = None,
|
||||||
scene_hints: Sequence[str] | None = None,
|
scene_hints: Sequence[str] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Transcribe a local audio file via Doubao flash ASR. Returns text."""
|
"""Transcribe a local audio file via Doubao flash ASR. Returns text.
|
||||||
|
|
||||||
|
``api_key`` (new-console X-Api-Key) is preferred; without it the legacy
|
||||||
|
App ID + Access Token pair (``X-Api-App-Key`` / ``X-Api-Access-Key``)
|
||||||
|
is used.
|
||||||
|
"""
|
||||||
path = Path(audio_path)
|
path = Path(audio_path)
|
||||||
if not path.is_file():
|
if not path.is_file():
|
||||||
raise FileNotFoundError(str(path))
|
raise FileNotFoundError(str(path))
|
||||||
@@ -143,12 +149,15 @@ def transcribe_flash(
|
|||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"X-Api-App-Key": appid,
|
|
||||||
"X-Api-Access-Key": token,
|
|
||||||
"X-Api-Resource-Id": _RESOURCE_ID,
|
"X-Api-Resource-Id": _RESOURCE_ID,
|
||||||
"X-Api-Request-Id": str(uuid.uuid4()),
|
"X-Api-Request-Id": str(uuid.uuid4()),
|
||||||
"X-Api-Sequence": "-1",
|
"X-Api-Sequence": "-1",
|
||||||
}
|
}
|
||||||
|
if api_key:
|
||||||
|
headers["X-Api-Key"] = api_key
|
||||||
|
else:
|
||||||
|
headers["X-Api-App-Key"] = appid
|
||||||
|
headers["X-Api-Access-Key"] = token
|
||||||
request_body: dict[str, Any] = {
|
request_body: dict[str, Any] = {
|
||||||
"model_name": "bigmodel",
|
"model_name": "bigmodel",
|
||||||
"enable_itn": True,
|
"enable_itn": True,
|
||||||
@@ -162,7 +171,7 @@ def transcribe_flash(
|
|||||||
request_body["corpus"] = corpus
|
request_body["corpus"] = corpus
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
"user": {"uid": uid or appid},
|
"user": {"uid": uid or appid or "xiaohe"},
|
||||||
"audio": {
|
"audio": {
|
||||||
"data": base64.b64encode(audio_bytes).decode("ascii"),
|
"data": base64.b64encode(audio_bytes).decode("ascii"),
|
||||||
"format": fmt,
|
"format": fmt,
|
||||||
|
|||||||
+22
-10
@@ -22,10 +22,10 @@ _FORMAT_CHOICES = ["mp3", "wav", "pcm"]
|
|||||||
|
|
||||||
|
|
||||||
def _get_credentials():
|
def _get_credentials():
|
||||||
"""Get Volcengine appid + access_token (STT, legacy TTS).
|
"""Get legacy Volcengine appid + access_token (STT/TTS fallback).
|
||||||
|
|
||||||
STT still uses the legacy appid/token app auth; the newer X-Api-Key path is
|
The new-console X-Api-Key (``secrets.api_keys.volc_tts``) is preferred for
|
||||||
TTS-only and lives in ``_get_tts_credentials``.
|
both TTS and STT; the legacy appid/token pair survives as fallback.
|
||||||
"""
|
"""
|
||||||
appid = config.resolve_key("secrets.volcengine.app_id", "VOLC_APPID")
|
appid = config.resolve_key("secrets.volcengine.app_id", "VOLC_APPID")
|
||||||
access_token = config.resolve_key(
|
access_token = config.resolve_key(
|
||||||
@@ -36,8 +36,8 @@ def _get_credentials():
|
|||||||
return appid, access_token
|
return appid, access_token
|
||||||
|
|
||||||
|
|
||||||
def _get_tts_credentials() -> dict:
|
def _get_voice_credentials() -> dict:
|
||||||
"""TTS credentials from config (new api_key preferred).
|
"""TTS/STT credentials from config (new api_key preferred).
|
||||||
|
|
||||||
Newer X-Api-Key auth (``secrets.api_keys.volc_tts`` / ``VOLC_TTS_API_KEY``)
|
Newer X-Api-Key auth (``secrets.api_keys.volc_tts`` / ``VOLC_TTS_API_KEY``)
|
||||||
takes precedence; legacy appid + access_token is the fallback.
|
takes precedence; legacy appid + access_token is the fallback.
|
||||||
@@ -61,7 +61,7 @@ def _synthesize_sync(
|
|||||||
output_path: str,
|
output_path: str,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Synchronous wrapper around async TTS."""
|
"""Synchronous wrapper around async TTS."""
|
||||||
creds = _get_tts_credentials()
|
creds = _get_voice_credentials()
|
||||||
if not creds:
|
if not creds:
|
||||||
raise click.UsageError(
|
raise click.UsageError(
|
||||||
"Volcengine TTS credentials not set. Run:\n"
|
"Volcengine TTS credentials not set. Run:\n"
|
||||||
@@ -164,11 +164,22 @@ def tts_cmd(text, file, speaker, fmt, speed, output):
|
|||||||
@handle_errors
|
@handle_errors
|
||||||
def stt_cmd(input_path, output, history_file, hotword, correct):
|
def stt_cmd(input_path, output, history_file, hotword, correct):
|
||||||
"""使用豆包/火山引擎极速 ASR 将语音转为文本。"""
|
"""使用豆包/火山引擎极速 ASR 将语音转为文本。"""
|
||||||
appid, access_token = _get_credentials()
|
creds = _get_voice_credentials()
|
||||||
if not appid or not access_token:
|
if not creds:
|
||||||
raise click.UsageError(
|
raise click.UsageError(
|
||||||
"Volcengine credentials not set. Run:\n"
|
"Volcengine ASR credentials not set. Run:\n"
|
||||||
" mytoolkit env set secrets.volcengine.app_id <appid>\n"
|
" mytoolkit env set secrets.api_keys.volc_tts <api_key>\n"
|
||||||
|
" (or legacy) mytoolkit env set secrets.volcengine.app_id <appid>\n"
|
||||||
|
" mytoolkit env set secrets.volcengine.access_token <token>"
|
||||||
|
)
|
||||||
|
api_key = creds.get("api_key")
|
||||||
|
appid = creds.get("appid", "")
|
||||||
|
access_token = creds.get("token", "")
|
||||||
|
if not api_key and not (appid and access_token):
|
||||||
|
raise click.UsageError(
|
||||||
|
"Volcengine ASR credentials not set. Run:\n"
|
||||||
|
" mytoolkit env set secrets.api_keys.volc_tts <api_key>\n"
|
||||||
|
" (or legacy) mytoolkit env set secrets.volcengine.app_id <appid>\n"
|
||||||
" mytoolkit env set secrets.volcengine.access_token <token>"
|
" mytoolkit env set secrets.volcengine.access_token <token>"
|
||||||
)
|
)
|
||||||
history = None
|
history = None
|
||||||
@@ -185,6 +196,7 @@ def stt_cmd(input_path, output, history_file, hotword, correct):
|
|||||||
appid,
|
appid,
|
||||||
access_token,
|
access_token,
|
||||||
input_path,
|
input_path,
|
||||||
|
api_key=api_key,
|
||||||
history=history,
|
history=history,
|
||||||
hotwords=hotwords,
|
hotwords=hotwords,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user