主播列表的码率改为直播实际档位下拉,没选过时默认第二档
原来是一个手填的码率上限(Kbps),现在改成直播的实际档位(蓝光 8M / 高清…): - 读到档位后,主播那一行渲染成下拉,选完立即生效;正在录制时换档会自动重录。 - 没手动选过(bitrate 0)的主播按**自上往下第二档**定下来(如 蓝光 8M / 蓝光 4M / 高清 就选蓝光 4M,只有一档就用那一档),不会一上来就吃满 最高档;已经手动选过的永远不动。 - 档位要开播后读直播源列表才知道,读到以后(录制开始时、或页面点「档位」按钮) 缓存进 config.json 的 qualities,所以没开播也能看和改;启动时会把「有缓存但还 没定过码率」的主播按第二档补齐。 - 从来没读过档位的行仍然是手填输入框,旁边多了个「档位」按钮去直播间接一次。 后端:新增 `GET /api/streamer/qualities?uid=…`(同一主播 10 秒内只读一次), `/api/status` 的每个主播多了 `qualities`(按码率从高到低)和 `qualityName`; 抽出 `newStreamInfo()`/`fetchStreamQualities()`,`getStreamURL()` 取流时顺手缓存 档位,并在 bitrate 为 0 时改用刚定下来的默认档位(否则还是最高档)。 档位相关的纯逻辑放在 config.go:`sortQualitiesDesc` / `defaultQualityBitrate` / `qualityNameFor` / `sameQualities` / `setStreamerQualities` / `applyCachedDefaultQualities`。 测试:qualities_test.go 7 个用例(排序、默认第二档的 5 种档位数、档位名匹配、 写配置时不覆盖手动选择、启动补齐、JSON 存取往返);浏览器实测 5 组断言全过 (下拉选中当前档位、换档服务端立即变、无档位时保留输入框+按钮、启动默认第二档、 手填仍可用),verify_streamer_br.py / verify_pick.py / verify_settings.py 无回归; go test ./...、gofmt、go vet 干净。
This commit is contained in:
@@ -86,20 +86,65 @@ func checkFFmpegPath(path string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 获取 uid 的直播源(flv),bitrate 为 0 时取码率最高的源,否则取码率不超过 bitrate(Kbps)的最高档
|
||||
func getStreamURL(uid, bitrate int) (url string, quality string, err error) {
|
||||
// 连到该主播的直播间并取直播流信息(获取直播源和探测码率档位都用它)
|
||||
func newStreamInfo(uid int) (*acfundanmu.StreamInfo, error) {
|
||||
var ac *acfundanmu.AcFunLive
|
||||
var err error
|
||||
err = runThrice(func() error {
|
||||
ac, err = acfundanmu.NewAcFunLive(acfundanmu.SetLiverUID(int64(uid)))
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ac.GetStreamInfo(), nil
|
||||
}
|
||||
|
||||
// 把直播源列表转成码率档位
|
||||
func streamTiers(list []acfundanmu.StreamURL) []qualityTier {
|
||||
tiers := make([]qualityTier, 0, len(list))
|
||||
for _, st := range list {
|
||||
tiers = append(tiers, qualityTier{Name: st.QualityName, Bitrate: st.Bitrate})
|
||||
}
|
||||
return tiers
|
||||
}
|
||||
|
||||
// 取该主播当前的码率档位(没开播或拿不到直播源时返回错误)
|
||||
func fetchStreamQualities(uid int) ([]qualityTier, error) {
|
||||
info, err := newStreamInfo(uid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info == nil || len(info.StreamList) == 0 {
|
||||
return nil, fmt.Errorf("uid 为%d的主播现在没有可用的直播源(没开播?)", uid)
|
||||
}
|
||||
return streamTiers(info.StreamList), nil
|
||||
}
|
||||
|
||||
// 获取 uid 的直播源(flv),bitrate 为 0 时取码率最高的源,否则取码率不超过 bitrate(Kbps)的最高档
|
||||
func getStreamURL(uid, bitrate int) (url string, quality string, err error) {
|
||||
sInfo, err := newStreamInfo(uid)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
sInfo := ac.GetStreamInfo()
|
||||
if len(sInfo.StreamList) == 0 {
|
||||
if sInfo == nil || len(sInfo.StreamList) == 0 {
|
||||
return "", "", fmt.Errorf("uid 为%d的主播没有可用的直播源", uid)
|
||||
}
|
||||
// 顺手把码率档位记下来:页面上要用它做下拉,没开播时靠缓存显示
|
||||
if tiers := streamTiers(sInfo.StreamList); len(tiers) > 0 {
|
||||
if setStreamerQualities(uid, tiers) {
|
||||
saveConfig()
|
||||
}
|
||||
// 还没设过码率的(0)刚被默认档位定下来,这里跟着用它,别又回到最高档
|
||||
if bitrate == 0 {
|
||||
for _, u := range config.UIDs {
|
||||
if u.UID == uid {
|
||||
bitrate = u.Bitrate
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// StreamList 按码率升序排列
|
||||
st := sInfo.StreamList[len(sInfo.StreamList)-1]
|
||||
if bitrate > 0 {
|
||||
|
||||
Reference in New Issue
Block a user