tokenFactory/relay/helper/video_seedance_payload_bill...

116 lines
3.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package helper
import (
"net/http/httptest"
"strconv"
"testing"
"github.com/QuantumNous/new-api/common"
relaycommon "github.com/QuantumNous/new-api/relay/common"
"github.com/QuantumNous/new-api/setting/ratio_setting"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/require"
)
// 与用户提供的 playground JSON 等价(字段语义一致),用于演练 ModelPriceHelperVideo 的估值链路。
func seedancePlaygroundTaskReq(t *testing.T) relaycommon.TaskSubmitReq {
t.Helper()
const payload = `{
"model": "Seedance2.0",
"prompt": "生成一个小猫嗷嗷叫的视频",
"n": 1,
"size": "960x540",
"fps": 24,
"duration": 5,
"motion": 0.6,
"negative_prompt": "",
"seed": null,
"images": []
}`
var req relaycommon.TaskSubmitReq
require.NoError(t, common.UnmarshalJsonStr(payload, &req))
return req
}
// TestSeedancePlaygroundJSON_PerSecondQuota 演示:若全局为 Seedance2.0 配置了「文生视频按秒」规则,
// 则预扣额度 = ceil(duration)×每秒单价(USD)×QuotaPerUnit×分组倍率×渠道折扣。
// 单价需替换为你们控制台真实配置;此处用 0.01 USD/秒便于断言公式。
func TestSeedancePlaygroundJSON_PerSecondQuota(t *testing.T) {
gin.SetMode(gin.TestMode)
prevRules := ratio_setting.VideoPricingRules2JSONString()
defer func() { _ = ratio_setting.UpdateVideoPricingRulesByJSONString(prevRules) }()
const pricePerSecUSD = 0.01
cfg := `{"Seedance2.0":{"text_to_video_per_second":[{"resolution":"540p","has_audio":false,"price":` +
strconv.FormatFloat(pricePerSecUSD, 'g', -1, 64) + `}]}}`
require.NoError(t, ratio_setting.UpdateVideoPricingRulesByJSONString(cfg))
w := httptest.NewRecorder()
c, _ := gin.CreateTestContext(w)
req := seedancePlaygroundTaskReq(t)
c.Set("task_request", req)
relayInfo := &relaycommon.RelayInfo{
UserGroup: "test-group",
UsingGroup: "default",
OriginModelName: req.Model,
}
pd, err := ModelPriceHelperVideo(c, relayInfo)
require.NoError(t, err)
ctx := estimateVideoRequestContext(c)
require.Equal(t, videoBillingModeTextToVideo, ctx.Mode, "images 为空应为文生视频")
require.Equal(t, 960, ctx.Width)
require.Equal(t, 540, ctx.Height)
require.Equal(t, 5, ctx.DurationSec)
sec := 5
if ctx.DurationSec > 0 {
sec = ctx.DurationSec
}
want := int(common.QuotaPerUnit * float64(sec) * pricePerSecUSD * pd.GroupRatioInfo.GroupRatio)
require.Equal(t, want, pd.Quota,
"应与 ceil(秒)×单价×QuotaPerUnit×group 一致(渠道 id=0 无折扣)")
t.Logf("estimate ctx: mode=%s WxH=%dx%d durationSec=%d fps(estimate)=%d inputTextTokens≈%d",
ctx.Mode, ctx.Width, ctx.Height, ctx.DurationSec, ctx.FPS, ctx.InputTextTokens)
t.Logf("preconsume quota=%d (QuotaPerUnit=%.0f groupRatio=%.4f)",
pd.Quota, common.QuotaPerUnit, pd.GroupRatioInfo.GroupRatio)
}
func TestPickAudioPriceByResolution_RoundsUpPseudo540p(t *testing.T) {
rows := []ratio_setting.VideoResolutionAudioPriceRule{
{Resolution: "480p", HasAudio: false, Price: 9},
{Resolution: "540p", HasAudio: false, Price: 8},
{Resolution: "720p", HasAudio: false, Price: 10},
}
price, ok := pickAudioPriceByResolution(videoEstimateContext{
Width: 864,
Height: 496,
}, false, rows)
require.True(t, ok)
require.Equal(t, 8.0, price, "864x496 exceeds 480p bounds, so it should round up to 540p")
}
func TestPickAudioPriceByResolution_UsesTargetAspectRatio(t *testing.T) {
rows := []ratio_setting.VideoResolutionAudioPriceRule{
{Resolution: "480p", HasAudio: false, Price: 9},
{Resolution: "540p", HasAudio: false, Price: 8},
{Resolution: "720p", HasAudio: false, Price: 10},
}
price, ok := pickAudioPriceByResolution(videoEstimateContext{
Width: 1120,
Height: 480,
}, false, rows)
require.True(t, ok)
require.Equal(t, 9.0, price, "21:9 1120x480 should fit the 480p tier for that aspect ratio")
}