You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
4.2 KiB
143 lines
4.2 KiB
package bvc |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
bm "go-common/library/net/http/blademaster" |
|
"go-common/library/net/metadata" |
|
"go-common/library/sync/errgroup" |
|
"go-common/library/xstr" |
|
"math" |
|
"net/url" |
|
"strconv" |
|
) |
|
|
|
const livePlayURLHost = "live-playurl.bilibili.co" |
|
const livePlayURLAddr = "http://live-playurl.bilibili.co/room/v1/Room/playUrl" |
|
const livePlayURLMultiAddr = "http://%s/stream/v1/multiplayurl" |
|
|
|
type PlayUrlItem struct { |
|
RoomId int64 `json:"room_id"` |
|
CurrentQuality int64 `json:"current_quality"` |
|
AcceptQuality []int64 `json:"accept_quality"` |
|
Url map[string]string `json:"url"` |
|
} |
|
type respPlayUrl struct { |
|
Code int `json:"code"` |
|
Msg string `json:"msg"` |
|
Data []*PlayUrlItem `json:"data"` |
|
} |
|
|
|
// 历史原因,单个的接口和视频云@yuanfeng确认数据结构不统一,后面统一,暂时先不用 |
|
// @see http://live-hub.bilibili.co/doc/playurl/ |
|
func (c *Client) GetPlayUrl(ctx *bm.Context, cid, quality, ptype, needHttps, unicomFree int64, platform string) (resp *respPlayUrl) { |
|
cli := bm.NewClient(c.getConf()) |
|
|
|
param := url.Values{} |
|
|
|
param.Set("cid", strconv.FormatInt(cid, 10)) |
|
param.Set("quality", strconv.FormatInt(quality, 10)) |
|
param.Set("platform", platform) |
|
param.Set("ptype", strconv.FormatInt(ptype, 10)) |
|
param.Set("https_url_req", strconv.FormatInt(needHttps, 10)) |
|
param.Set("unicom_free", strconv.FormatInt(unicomFree, 10)) |
|
|
|
err := cli.Get(ctx, livePlayURLAddr, "", param, &resp) |
|
if err != nil { |
|
log.Error("call %s error(%v)", livePlayURLAddr, err) |
|
return |
|
} |
|
if resp.Code != ecode.OK.Code() { |
|
log.Error("call %s response error, code(%d) message(%s)", livePlayURLAddr, resp.Code, resp.Msg) |
|
return |
|
} |
|
return |
|
} |
|
|
|
// 批量接口,一次最好20个 |
|
func (c *Client) GetPlayUrlMulti(ctx context.Context, roomIds []int64, |
|
needHttps, quality, build int64, platform string) (result map[int64]*PlayUrlItem) { |
|
cli := bm.NewClient(c.getConf()) |
|
result = make(map[int64]*PlayUrlItem) |
|
|
|
userIp := metadata.String(ctx, metadata.RemoteIP) |
|
if userIp == "127.0.0.1" || c.mock == "1" { |
|
userIp = "222.73.196.18" |
|
} |
|
bvcHost := c.getBvcHost(livePlayURLHost) |
|
|
|
if quality == 0 { |
|
quality = 4 |
|
} |
|
|
|
chunkSize := 20 |
|
lens := len(roomIds) |
|
if lens <= 0 { |
|
return |
|
} |
|
// 批次 |
|
chunkNum := int(math.Ceil(float64(lens) / float64(chunkSize))) |
|
wg, _ := errgroup.WithContext(ctx) |
|
// 空间换时间 |
|
chunkResult := make([][]*PlayUrlItem, chunkNum) |
|
for i := 1; i <= chunkNum; i++ { |
|
x := i |
|
wg.Go(func() error { |
|
param := url.Values{} |
|
chunkRoomIds := make([]int64, 20) |
|
if x == chunkNum { |
|
chunkRoomIds = roomIds[(x-1)*chunkSize:] |
|
} else { |
|
chunkRoomIds = roomIds[(x-1)*chunkSize : x*chunkSize] |
|
} |
|
param.Set("room_ids", xstr.JoinInts(chunkRoomIds)) |
|
param.Set("platform", platform) |
|
param.Set("https_url_req", strconv.FormatInt(needHttps, 10)) |
|
param.Set("quality", strconv.FormatInt(quality, 10)) |
|
param.Set("build", strconv.FormatInt(build, 10)) |
|
param.Set("req_biz", "live-app-interface") |
|
|
|
var resp respPlayUrl |
|
bvcUrl := fmt.Sprintf(livePlayURLMultiAddr, bvcHost) |
|
req, err := cli.NewRequest("GET", bvcUrl, userIp, param) |
|
if err != nil { |
|
log.Error("GetPlayUrlMulti client.NewRequest: get error(%v)", err) |
|
return nil |
|
} |
|
//req.Header.Add("x-backend-bili-real-ip", userIp) |
|
if err := cli.Do(ctx, req, &resp); err != nil { |
|
log.Error("GetPlayUrlMulti client.Do: get error(%v)", err) |
|
return nil |
|
} |
|
if resp.Code != 0 { |
|
log.Error("GetPlayUrlMulti call %s response error, code(%d) message(%s) param(%+v) room_ids(%+v)", bvcUrl, resp.Code, resp.Msg, param, chunkRoomIds) |
|
return nil |
|
} |
|
if resp.Data == nil || len(resp.Data) <= 0 { |
|
log.Warn("GetPlayUrlMulti call %s response empty, code(%d) message(%s) param(%+v) room_ids(%+v)", bvcUrl, resp.Code, resp.Msg, param, chunkRoomIds) |
|
return nil |
|
} |
|
|
|
//chunkResult = append(chunkResult, resp.Data) |
|
chunkResult[x-1] = resp.Data |
|
|
|
return nil |
|
}) |
|
} |
|
if err := wg.Wait(); err != nil { |
|
log.Error("GetPlayUrlMulti get playurl wait error(%+v)", err) |
|
return nil |
|
} |
|
// 整理数据 |
|
for _, chunkItemList := range chunkResult { |
|
for _, item := range chunkItemList { |
|
if item != nil { |
|
result[item.RoomId] = item |
|
} |
|
} |
|
} |
|
|
|
return |
|
}
|
|
|