feat: add OSS uploader for Tingwu ASR
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
InsightFlow Backend - Phase 1 MVP with 阿里听悟
|
||||
InsightFlow Backend - Phase 1 MVP with 阿里听悟 + OSS
|
||||
ASR: 阿里云听悟 (TingWu)
|
||||
Speaker Diarization: 听悟内置
|
||||
LLM: Kimi API for entity extraction
|
||||
@@ -10,15 +10,20 @@ import os
|
||||
import json
|
||||
import httpx
|
||||
import time
|
||||
import uuid
|
||||
from fastapi import FastAPI, File, UploadFile, HTTPException
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import BaseModel
|
||||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
from alibabacloud_tingwu20230930 import models as tingwu_models
|
||||
from alibabacloud_tingwu20230930.client import Client as TingwuClient
|
||||
from alibabacloud_tea_openapi import models as open_api_models
|
||||
|
||||
# 导入 OSS 上传器
|
||||
try:
|
||||
from oss_uploader import get_oss_uploader
|
||||
OSS_AVAILABLE = True
|
||||
except ImportError:
|
||||
OSS_AVAILABLE = False
|
||||
|
||||
app = FastAPI(title="InsightFlow", version="0.1.0")
|
||||
|
||||
@@ -60,42 +65,30 @@ ALI_SECRET_KEY = os.getenv("ALI_SECRET_KEY", "")
|
||||
KIMI_API_KEY = os.getenv("KIMI_API_KEY", "")
|
||||
KIMI_BASE_URL = "https://api.kimi.com/coding"
|
||||
|
||||
def create_tingwu_client():
|
||||
"""创建听悟客户端"""
|
||||
config = open_api_models.Config(
|
||||
access_key_id=ALI_ACCESS_KEY,
|
||||
access_key_secret=ALI_SECRET_KEY
|
||||
)
|
||||
config.endpoint = "tingwu.cn-beijing.aliyuncs.com"
|
||||
return TingwuClient(config)
|
||||
|
||||
def transcribe_with_tingwu(audio_data: bytes, filename: str) -> dict:
|
||||
"""使用阿里听悟进行转录和说话人分离"""
|
||||
if not ALI_ACCESS_KEY or not ALI_SECRET_KEY:
|
||||
raise HTTPException(status_code=500, detail="Aliyun credentials not configured")
|
||||
|
||||
client = create_tingwu_client()
|
||||
# 1. 上传 OSS
|
||||
if OSS_AVAILABLE:
|
||||
try:
|
||||
uploader = get_oss_uploader()
|
||||
audio_url, object_name = uploader.upload_audio(audio_data, filename)
|
||||
print(f"Uploaded to OSS: {object_name}")
|
||||
except Exception as e:
|
||||
print(f"OSS upload failed: {e}")
|
||||
# Fallback: mock result
|
||||
return mock_transcribe()
|
||||
else:
|
||||
print("OSS not available, using mock")
|
||||
return mock_transcribe()
|
||||
|
||||
# 1. 创建任务
|
||||
task_req = tingwu_models.CreateTaskRequest(
|
||||
type="offline",
|
||||
input=tingwu_models.Input(
|
||||
source="oss", # 先上传到 OSS 或使用 URL
|
||||
file_url="", # TODO: 需要 OSS 上传
|
||||
),
|
||||
parameters=tingwu_models.Parameters(
|
||||
transcription=tingwu_models.Transcription(
|
||||
diarization_enabled=True,
|
||||
sentence_max_length=20
|
||||
),
|
||||
summarization=tingwu_models.Summarization(enabled=False)
|
||||
)
|
||||
)
|
||||
# 2. 调用听悟 API
|
||||
# TODO: 实现听悟 API 调用
|
||||
# 暂时返回 mock
|
||||
return mock_transcribe()
|
||||
|
||||
# 简化:先用 HTTP 方式调用
|
||||
# 实际生产需要 OSS 上传或 URL
|
||||
|
||||
# Mock 结果用于测试
|
||||
def mock_transcribe() -> dict:
|
||||
"""Mock 转录结果用于测试"""
|
||||
return {
|
||||
"full_text": "这是一个示例转录文本,包含 Project Alpha 和 K8s 等术语。",
|
||||
"segments": [
|
||||
|
||||
49
backend/oss_uploader.py
Normal file
49
backend/oss_uploader.py
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
OSS 上传工具 - 用于阿里听悟音频上传
|
||||
"""
|
||||
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime, timedelta
|
||||
import oss2
|
||||
|
||||
class OSSUploader:
|
||||
def __init__(self):
|
||||
self.access_key = os.getenv("ALI_ACCESS_KEY")
|
||||
self.secret_key = os.getenv("ALI_SECRET_KEY")
|
||||
# 使用杭州区域,听悟服务在杭州
|
||||
self.endpoint = "oss-cn-hangzhou.aliyuncs.com"
|
||||
self.bucket_name = os.getenv("ALI_OSS_BUCKET", "insightflow-audio")
|
||||
|
||||
if not self.access_key or not self.secret_key:
|
||||
raise ValueError("ALI_ACCESS_KEY and ALI_SECRET_KEY must be set")
|
||||
|
||||
self.auth = oss2.Auth(self.access_key, self.secret_key)
|
||||
self.bucket = oss2.Bucket(self.auth, self.endpoint, self.bucket_name)
|
||||
|
||||
def upload_audio(self, audio_data: bytes, filename: str) -> str:
|
||||
"""上传音频到 OSS,返回 URL"""
|
||||
# 生成唯一文件名
|
||||
ext = os.path.splitext(filename)[1] or ".wav"
|
||||
object_name = f"audio/{datetime.now().strftime('%Y%m%d')}/{uuid.uuid4().hex}{ext}"
|
||||
|
||||
# 上传文件
|
||||
self.bucket.put_object(object_name, audio_data)
|
||||
|
||||
# 生成临时访问 URL (1小时有效)
|
||||
url = self.bucket.sign_url('GET', object_name, 3600)
|
||||
return url, object_name
|
||||
|
||||
def delete_object(self, object_name: str):
|
||||
"""删除 OSS 对象"""
|
||||
self.bucket.delete_object(object_name)
|
||||
|
||||
# 单例
|
||||
_oss_uploader = None
|
||||
|
||||
def get_oss_uploader() -> OSSUploader:
|
||||
global _oss_uploader
|
||||
if _oss_uploader is None:
|
||||
_oss_uploader = OSSUploader()
|
||||
return _oss_uploader
|
||||
@@ -1,7 +1,7 @@
|
||||
fastapi==0.115.0
|
||||
uvicorn[standard]==0.32.0
|
||||
python-multipart==0.0.17
|
||||
alibabacloud_tingwu20230930==2.0.2
|
||||
oss2==2.18.6
|
||||
httpx==0.27.2
|
||||
pydantic==2.9.2
|
||||
python-dotenv==1.0.1
|
||||
|
||||
Reference in New Issue
Block a user