Files
AudioScribe/transcribe_legacy.py
Misaka_Company e4c6f793e1 Add HTTP retry mechanism and request timeout to transcribe_legacy
Use requests Session with Retry adapter (5 retries, backoff factor 1)
and add 30s timeout to both submit and query requests for better
reliability against transient network errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-08 14:01:32 +08:00

170 lines
5.0 KiB
Python

import json
import os
import sys
import time
import uuid
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from boto3 import client as s3_client
from botocore.config import Config
from dotenv import load_dotenv
load_dotenv()
APP_ID = os.getenv("X_API_APP_KEY")
ACCESS_TOKEN = os.getenv("X_API_ACCESS_KEY")
RESOURCE_ID = os.getenv("X_API_RESOURCE_ID")
S3_ENDPOINT = os.getenv("S3_ENDPOINT")
S3_ACCESS_KEY_ID = os.getenv("S3_ACCESS_KEY_ID")
S3_SECRET_ACCESS_KEY = os.getenv("S3_SECRET_ACCESS_KEY")
S3_BUCKET = os.getenv("S3_BUCKET")
SUBMIT_URL = "https://openspeech.bytedance.com/api/v3/auc/bigmodel/submit"
QUERY_URL = "https://openspeech.bytedance.com/api/v3/auc/bigmodel/query"
retry = Retry(total=5, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
session = requests.Session()
session.mount("http://", HTTPAdapter(max_retries=retry))
session.mount("https://", HTTPAdapter(max_retries=retry))
s3 = s3_client(
"s3",
endpoint_url=S3_ENDPOINT,
aws_access_key_id=S3_ACCESS_KEY_ID,
aws_secret_access_key=S3_SECRET_ACCESS_KEY,
config=Config(signature_version="s3v4"),
region_name="auto",
)
def fmt_time(ms):
s = ms / 1000
m = int(s // 60)
sec = s % 60
return f"{m:02d}:{sec:05.2f}"
def build_markdown(data, audio_file):
result = data.get("result", {})
utterances = result.get("utterances", [])
duration = data.get("audio_info", {}).get("duration", 0)
speaker_order = []
for u in utterances:
sp = u.get("additions", {}).get("speaker", "unknown")
if sp not in speaker_order:
speaker_order.append(sp)
lines = [
"# 转写结果",
"",
f"**源文件**: {audio_file} ",
f"**音频时长**: {fmt_time(duration)} ",
f"**说话人数量**: {len(speaker_order)}",
f"**分句数量**: {len(utterances)}",
"",
"---",
"",
"## 按时间线",
"",
]
for u in utterances:
sp = u.get("additions", {}).get("speaker", "?")
start = u.get("start_time", 0)
end = u.get("end_time", 0)
t = u.get("text", "").strip()
if not t:
continue
lines.append(f"- **{fmt_time(start)} - {fmt_time(end)}** **说话人{sp}** {t}")
lines.append("")
return "\n".join(lines)
def make_headers(task_id, with_sequence=False):
headers = {
"X-Api-App-Key": APP_ID,
"X-Api-Access-Key": ACCESS_TOKEN,
"X-Api-Resource-Id": RESOURCE_ID,
"X-Api-Request-Id": task_id,
}
if with_sequence:
headers["X-Api-Sequence"] = "-1"
return headers
audio_file = sys.argv[1] if len(sys.argv) > 1 else "2026年05月26日 17点53分.mp3"
audio_ext = os.path.splitext(audio_file)[1].lstrip(".")
audio_name = os.path.splitext(os.path.basename(audio_file))[0]
obj_name = f"audio/{uuid.uuid4().hex[:8]}_{os.path.basename(audio_file)}"
print(f"Uploading {audio_file} ...")
s3.upload_file(audio_file, S3_BUCKET, obj_name)
url = s3.generate_presigned_url(
"get_object",
Params={"Bucket": S3_BUCKET, "Key": obj_name},
ExpiresIn=3600,
)
task_id = str(uuid.uuid4())
headers = make_headers(task_id, with_sequence=True)
body = {
"user": {"uid": "audioscribe"},
"audio": {"url": url, "format": audio_ext},
"request": {
"model_name": "bigmodel",
"enable_itn": True,
"enable_punc": True,
"enable_ddc": True,
"enable_speaker_info": True,
"show_utterances": True,
},
}
resp = session.post(SUBMIT_URL, json=body, headers=headers, timeout=30)
logid = resp.headers.get("X-Tt-Logid", "")
status = resp.headers.get("X-Api-Status-Code", "")
print(f"Submit: {status}")
if status != "20000000":
print(f"FAILED: {resp.headers.get('X-Api-Message', '')}")
else:
while True:
resp = session.post(
QUERY_URL,
json={},
headers={
**make_headers(task_id),
"X-Tt-Logid": logid,
},
timeout=30,
)
code = resp.headers.get("X-Api-Status-Code", "")
if code == "20000000":
data = resp.json()
text = data.get("result", {}).get("text", "")
utterances = data.get("result", {}).get("utterances", [])
os.makedirs("output", exist_ok=True)
json_path = f"output/{audio_name}_转写结果.json"
with open(json_path, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
md_path = f"output/{audio_name}_转写结果.md"
with open(md_path, "w", encoding="utf-8") as f:
f.write(build_markdown(data, audio_file))
print(f"Done ({len(text)} chars, {len(utterances)} utterances)")
print(f"Saved: {json_path}, {md_path}")
break
elif code in ("20000001", "20000002"):
print(f" Processing... ({code})")
time.sleep(5)
else:
print(f"FAILED: {code} {resp.headers.get('X-Api-Message', '')}")
break
print("\nAll done.")