fix: clarify seedance reference video failures
This commit is contained in:
@@ -263,6 +263,9 @@ func aiUpstreamErrorDetail(body []byte) string {
|
||||
}
|
||||
if err := json.Unmarshal(body, &payload); err == nil {
|
||||
if payload.Error.Message != "" {
|
||||
if detail := friendlyUpstreamError(payload.Error.Code, payload.Error.Message); detail != "" {
|
||||
return safeUpstreamText(detail)
|
||||
}
|
||||
if payload.Error.Code != "" {
|
||||
return safeUpstreamText(payload.Error.Code + " " + payload.Error.Message)
|
||||
}
|
||||
@@ -278,6 +281,14 @@ func aiUpstreamErrorDetail(body []byte) string {
|
||||
return safeUpstreamText(text)
|
||||
}
|
||||
|
||||
func friendlyUpstreamError(code string, message string) string {
|
||||
lowerCode := strings.ToLower(strings.TrimSpace(code))
|
||||
if strings.Contains(lowerCode, "inputvideosensitivecontentdetected") || strings.Contains(lowerCode, "privacyinformation") {
|
||||
return strings.TrimSpace(code + " 参考视频疑似包含真人或隐私信息,火山方舟拒绝使用普通 URL 作为真人视频参考;请改用不含真人的视频、官方允许的模型产物,或已授权的 asset:// 素材。原始错误:" + message)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func safeUpstreamText(text string) string {
|
||||
text = strings.Join(strings.Fields(strings.TrimSpace(text)), " ")
|
||||
runes := []rune(text)
|
||||
|
||||
@@ -12,6 +12,13 @@ func TestAIUpstreamErrorDetail(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAIUpstreamErrorDetailExplainsSensitiveVideo(t *testing.T) {
|
||||
got := aiUpstreamErrorDetail([]byte(`{"error":{"code":"InputVideoSensitiveContentDetected.PrivacyInformation","message":"The request failed because the input video may contain real person."}}`))
|
||||
if !strings.Contains(got, "参考视频疑似包含真人") || !strings.Contains(got, "asset://") {
|
||||
t.Fatalf("detail = %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSafeUpstreamTextTruncates(t *testing.T) {
|
||||
got := safeUpstreamText(strings.Repeat("错", 320))
|
||||
if len([]rune(got)) != 303 {
|
||||
|
||||
@@ -117,7 +117,25 @@ func ReferenceMedia(w http.ResponseWriter, r *http.Request, id string) {
|
||||
}
|
||||
|
||||
func referenceMediaDir() string {
|
||||
return filepath.Join("data", "reference-media")
|
||||
return filepath.Join(referenceDataDir(), "reference-media")
|
||||
}
|
||||
|
||||
func referenceDataDir() string {
|
||||
driver := strings.ToLower(strings.TrimSpace(config.Cfg.StorageDriver))
|
||||
dsn := strings.TrimSpace(config.Cfg.DatabaseDSN)
|
||||
if (driver == "" || driver == "sqlite") && dsn != "" && dsn != ":memory:" && !strings.HasPrefix(dsn, "file:") {
|
||||
pathPart := dsn
|
||||
if index := strings.Index(dsn, "?"); index >= 0 {
|
||||
pathPart = dsn[:index]
|
||||
}
|
||||
if filepath.IsAbs(pathPart) {
|
||||
return filepath.Dir(pathPart)
|
||||
}
|
||||
}
|
||||
if _, err := os.Stat("/app/data"); err == nil {
|
||||
return "/app/data"
|
||||
}
|
||||
return "data"
|
||||
}
|
||||
|
||||
func normalizeReferenceMediaType(contentType string, ext string) (string, string, bool) {
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package handler
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/basketikun/infinite-canvas/config"
|
||||
)
|
||||
|
||||
func TestNormalizeReferenceMediaTypeSupportsAudio(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -38,3 +43,14 @@ func TestReferenceMediaTypeMaxBytes(t *testing.T) {
|
||||
t.Fatalf("image max bytes = %d, want %d", got, referenceImageMaxBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReferenceMediaDirUsesAbsoluteSQLiteDataDir(t *testing.T) {
|
||||
previous := config.Cfg
|
||||
t.Cleanup(func() { config.Cfg = previous })
|
||||
root := t.TempDir()
|
||||
config.Cfg = config.Config{StorageDriver: "sqlite", DatabaseDSN: filepath.Join(root, "infinite-canvas.db")}
|
||||
|
||||
if got := referenceMediaDir(); got != filepath.Join(root, "reference-media") {
|
||||
t.Fatalf("referenceMediaDir = %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user