视频保存
This commit is contained in:
@@ -107,17 +107,20 @@ func (c *OpenAICompatibleClient) Transcribe(ctx context.Context, cfg *dao.STTCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3) 构造请求
|
// 3) 构造请求
|
||||||
endpoint := strings.TrimRight(cfg.Provider.BaseURL, "/") + "/audio/transcriptions"
|
endpoint := buildTranscriptionEndpoint(cfg.Provider.BaseURL)
|
||||||
|
if endpoint == "" {
|
||||||
|
return nil, fmt.Errorf("STT provider base_url is empty: provider=%s model=%s", cfg.Provider.ProviderCode, cfg.Model.ModelCode)
|
||||||
|
}
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, body)
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("构造 STT 请求失败: %w", err)
|
return nil, fmt.Errorf("构造 STT 请求失败: endpoint=%s provider=%s model=%s: %w", endpoint, cfg.Provider.ProviderCode, cfg.Model.ModelCode, err)
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+cfg.Key.APIKey)
|
req.Header.Set("Authorization", "Bearer "+cfg.Key.APIKey)
|
||||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
|
|
||||||
resp, err := c.httpClient.Do(req)
|
resp, err := c.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("调用 STT 接口失败: %w", err)
|
return nil, fmt.Errorf("调用 STT 接口失败: endpoint=%s provider=%s model=%s: %w", endpoint, cfg.Provider.ProviderCode, cfg.Model.ModelCode, err)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
@@ -132,7 +135,7 @@ func (c *OpenAICompatibleClient) Transcribe(ctx context.Context, cfg *dao.STTCon
|
|||||||
if len(preview) > 300 {
|
if len(preview) > 300 {
|
||||||
preview = preview[:300] + "..."
|
preview = preview[:300] + "..."
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("STT 接口返回 %d: %s", resp.StatusCode, preview)
|
return nil, fmt.Errorf("STT 接口返回 %d: endpoint=%s provider=%s model=%s body=%s", resp.StatusCode, endpoint, cfg.Provider.ProviderCode, cfg.Model.ModelCode, preview)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) 解析
|
// 4) 解析
|
||||||
@@ -151,6 +154,17 @@ func (c *OpenAICompatibleClient) Transcribe(ctx context.Context, cfg *dao.STTCon
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildTranscriptionEndpoint(baseURL string) string {
|
||||||
|
base := strings.TrimRight(strings.TrimSpace(baseURL), "/")
|
||||||
|
if base == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(base, "/audio/transcriptions") {
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
return base + "/audio/transcriptions"
|
||||||
|
}
|
||||||
|
|
||||||
// downloadAudio 从给定 URL 拉取音频内容,返回字节流 + 推断的文件名
|
// downloadAudio 从给定 URL 拉取音频内容,返回字节流 + 推断的文件名
|
||||||
//
|
//
|
||||||
// 文件名仅作为 multipart 的 filename 参数,主要决定 Content-Type 推断;
|
// 文件名仅作为 multipart 的 filename 参数,主要决定 Content-Type 推断;
|
||||||
|
|||||||
@@ -165,6 +165,12 @@ func (s *TranscribeService) runJob(transcriptID int64, rec meetingModel.MeetingR
|
|||||||
"model_code": cfg.Model.ModelCode,
|
"model_code": cfg.Model.ModelCode,
|
||||||
"key_id": cfg.Key.ID,
|
"key_id": cfg.Key.ID,
|
||||||
}).Error
|
}).Error
|
||||||
|
logs.Info(ctx, funcName, "已选择 STT 配置",
|
||||||
|
zap.Int64("transcript_id", transcriptID),
|
||||||
|
zap.String("provider_code", cfg.Provider.ProviderCode),
|
||||||
|
zap.String("model_code", cfg.Model.ModelCode),
|
||||||
|
zap.String("base_url", cfg.Provider.BaseURL),
|
||||||
|
zap.String("file_url", rec.FileURL))
|
||||||
|
|
||||||
result, err := s.sttClient.Transcribe(ctx, cfg, rec.FileURL, language)
|
result, err := s.sttClient.Transcribe(ctx, cfg, rec.FileURL, language)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ minio:
|
|||||||
secret_key: "echochat_2026-1s32dswW@#" # 密钥(与 docker-compose 中的 MINIO_ROOT_PASSWORD 一致)
|
secret_key: "echochat_2026-1s32dswW@#" # 密钥(与 docker-compose 中的 MINIO_ROOT_PASSWORD 一致)
|
||||||
bucket: "echochat" # 存储桶名称
|
bucket: "echochat" # 存储桶名称
|
||||||
use_ssl: false # 开发环境不使用 HTTPS
|
use_ssl: false # 开发环境不使用 HTTPS
|
||||||
public_base_url: "http://yl.z64.cn/echochat"
|
public_base_url: "https://yl.z64.cn/echochat"
|
||||||
|
|
||||||
# Node media-server 接入配置(Phase 2e-2 Task 7 HTTPMediaOrchestrator)
|
# Node media-server 接入配置(Phase 2e-2 Task 7 HTTPMediaOrchestrator)
|
||||||
# 对应 media-server/.env 的 MEDIA_INTERNAL_TOKEN + HTTP_PORT(默认 3300)
|
# 对应 media-server/.env 的 MEDIA_INTERNAL_TOKEN + HTTP_PORT(默认 3300)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ minio:
|
|||||||
secret_key: "echochat_2026-1s32dswW@#"
|
secret_key: "echochat_2026-1s32dswW@#"
|
||||||
bucket: "echochat"
|
bucket: "echochat"
|
||||||
use_ssl: false
|
use_ssl: false
|
||||||
public_base_url: "http://yl.z64.cn/echochat"
|
public_base_url: "https://yl.z64.cn/echochat"
|
||||||
|
|
||||||
# Node media-server 接入配置(Phase 2e-2 Task 7)
|
# Node media-server 接入配置(Phase 2e-2 Task 7)
|
||||||
media_server:
|
media_server:
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ REDIS_PASSWORD=echochat_2026-1s32dswW@#
|
|||||||
|
|
||||||
MINIO_ROOT_USER=echochat
|
MINIO_ROOT_USER=echochat
|
||||||
MINIO_ROOT_PASSWORD=echochat_2026-1s32dswW@#
|
MINIO_ROOT_PASSWORD=echochat_2026-1s32dswW@#
|
||||||
MINIO_PUBLIC_BASE_URL=http://yl.z64.cn/echochat
|
MINIO_PUBLIC_BASE_URL=https://yl.z64.cn/echochat
|
||||||
|
|
||||||
# ============================================================
|
# ============================================================
|
||||||
# Go backend
|
# Go backend
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ services:
|
|||||||
ECHOCHAT_MINIO_ACCESS_KEY: ${MINIO_ROOT_USER:-echochat}
|
ECHOCHAT_MINIO_ACCESS_KEY: ${MINIO_ROOT_USER:-echochat}
|
||||||
ECHOCHAT_MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-echochat123456}
|
ECHOCHAT_MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-echochat123456}
|
||||||
ECHOCHAT_MEDIA_SERVER_INTERNAL_TOKEN: ${MEDIA_INTERNAL_TOKEN:-internal-token-22xqs}
|
ECHOCHAT_MEDIA_SERVER_INTERNAL_TOKEN: ${MEDIA_INTERNAL_TOKEN:-internal-token-22xqs}
|
||||||
ECHOCHAT_MINIO_PUBLIC_BASE_URL: ${MINIO_PUBLIC_BASE_URL:-http://yl.z64.cn/echochat}
|
ECHOCHAT_MINIO_PUBLIC_BASE_URL: ${MINIO_PUBLIC_BASE_URL:-https://yl.z64.cn/echochat}
|
||||||
# media-server 失败回调共享密钥:与 media-server 服务的 INTERNAL_WEBHOOK_SECRET 保持一致
|
# media-server 失败回调共享密钥:与 media-server 服务的 INTERNAL_WEBHOOK_SECRET 保持一致
|
||||||
# 未配置时 go-service 会拒绝所有 webhook(Forbidden),录制失败状态将无法及时落 failed
|
# 未配置时 go-service 会拒绝所有 webhook(Forbidden),录制失败状态将无法及时落 failed
|
||||||
ECHOCHAT_MEETING_INTERNAL_WEBHOOK_SECRET: ${INTERNAL_WEBHOOK_SECRET:-internal-webhook-12xqs}
|
ECHOCHAT_MEETING_INTERNAL_WEBHOOK_SECRET: ${INTERNAL_WEBHOOK_SECRET:-internal-webhook-12xqs}
|
||||||
|
|||||||
Reference in New Issue
Block a user