From: qydysky Date: Wed, 21 Apr 2021 12:50:57 +0000 (+0800) Subject: hls动态调整清晰度 X-Git-Tag: v0.5.9~1^2~21 X-Git-Url: http://127.0.0.1:8081/?a=commitdiff_plain;h=ed0d5847ce8a8dfbbd22c45f5a3263f17c97afa2;p=bili_danmu%2F.git hls动态调整清晰度 hls网络阻塞切片猜测 清晰度允许范围bug修复 新大乱斗pk消息 --- diff --git a/CV/Var.go b/CV/Var.go index d6b8790..ff83527 100644 --- a/CV/Var.go +++ b/CV/Var.go @@ -14,6 +14,7 @@ var ( Live []string//直播流链接 Live_qn int//当前直播流质量 + Live_want_qn int//期望直播流质量 Roomid int Cookie syncmap.Map CookieOk bool// @@ -91,12 +92,24 @@ func init() { // ) // 不再需要 //允许的清晰度 -var AcceptQn = map[int]string{ - 10000:"原画", - 800:"4K", - 401:"蓝光(杜比)", - 400:"蓝光", - 250:"超清", - 150:"高清", - 80:"流畅", -} \ No newline at end of file + +var ( + AcceptQn = map[int]string{ + 10000:"原画", + 800:"4K", + 401:"蓝光(杜比)", + 400:"蓝光", + 250:"超清", + 150:"高清", + 80:"流畅", + } + Qn = map[int]string{// no change + 10000:"原画", + 800:"4K", + 401:"蓝光(杜比)", + 400:"蓝光", + 250:"超清", + 150:"高清", + 80:"流畅", + } +) \ No newline at end of file diff --git a/F/api.go b/F/api.go index 9a8be44..df2f69a 100644 --- a/F/api.go +++ b/F/api.go @@ -308,6 +308,14 @@ func Html() (missKey []string) { //是否在直播 c.Liveing = j.Roominitres.Data.LiveStatus == 1 + //未在直播,不获取直播流 + if !c.Liveing { + c.Live_qn = 0 + c.AcceptQn = c.Qn + c.Live = []string{} + return + } + //当前直播流 { type Stream_name struct { @@ -354,7 +362,7 @@ func Html() (missKey []string) { { var tmp = make(map[int]string) for _,v := range v.AcceptQn { - if s,ok := c.AcceptQn[v];ok{ + if s,ok := c.Qn[v];ok{ tmp[v] = s } } @@ -550,6 +558,14 @@ func getRoomPlayInfo() (missKey []string) { //是否在直播 c.Liveing = j.Data.LiveStatus == 1 + //未在直播,不获取直播流 + if !c.Liveing { + c.Live_qn = 0 + c.AcceptQn = c.Qn + c.Live = []string{} + return + } + //当前直播流 { type Stream_name struct { @@ -580,35 +596,49 @@ func getRoomPlayInfo() (missKey []string) { } else { apilog.L(`T: `, `默认hls`) } - - for _,v := range j.Data.PlayurlInfo.Playurl.Stream { - if v.ProtocolName != want_type.Protocol_name {continue} - - for _,v := range v.Format { - if v.FormatName != want_type.Format_name {continue} - - for _,v := range v.Codec { - if v.CodecName != want_type.Codec_name {continue} - - //当前直播流质量 - c.Live_qn = v.CurrentQn - //允许的清晰度 - { - var tmp = make(map[int]string) - for _,v := range v.AcceptQn { - if s,ok := c.AcceptQn[v];ok{ - tmp[v] = s + no_found_type := true + for { + for _,v := range j.Data.PlayurlInfo.Playurl.Stream { + if v.ProtocolName != want_type.Protocol_name {continue} + + for _,v := range v.Format { + if v.FormatName != want_type.Format_name {continue} + + for _,v := range v.Codec { + if v.CodecName != want_type.Codec_name {continue} + + //当前直播流质量 + c.Live_qn = v.CurrentQn + //允许的清晰度 + { + var tmp = make(map[int]string) + for _,v := range v.AcceptQn { + if s,ok := c.Qn[v];ok{ + tmp[v] = s + } } + c.AcceptQn = tmp + } + //直播流链接 + c.Live = []string{} + for _,v1 := range v.URLInfo { + c.Live = append(c.Live, v1.Host+v.BaseURL+v1.Extra) } - c.AcceptQn = tmp - } - //直播流链接 - c.Live = []string{} - for _,v1 := range v.URLInfo { - c.Live = append(c.Live, v1.Host+v.BaseURL+v1.Extra) } } } + if no_found_type { + if want_type.Protocol_name == "http_stream" { + apilog.L(`I: `, `不支持flv,使用hls`) + want_type = name_map[`hls`] + } else { + apilog.L(`I: `, `不支持hls,使用flv`) + want_type = name_map[`flv`] + } + no_found_type = false + } else { + break + } } } } @@ -629,7 +659,7 @@ func getRoomPlayInfoByQn() (missKey []string) { { AcceptQn := []int{} for k,_ := range c.AcceptQn { - if k <= c.Live_qn {AcceptQn = append(AcceptQn, k)} + if k <= c.Live_want_qn {AcceptQn = append(AcceptQn, k)} } MaxQn := 0 for i:=0; len(AcceptQn)>i; i+=1{ @@ -688,6 +718,14 @@ func getRoomPlayInfoByQn() (missKey []string) { //是否在直播 c.Liveing = j.Data.LiveStatus == 1 + //未在直播,不获取直播流 + if !c.Liveing { + c.Live_qn = 0 + c.AcceptQn = c.Qn + c.Live = []string{} + return + } + //当前直播流 { type Stream_name struct { @@ -719,36 +757,53 @@ func getRoomPlayInfoByQn() (missKey []string) { apilog.L(`T: `, `默认hls`) } - for _,v := range j.Data.PlayurlInfo.Playurl.Stream { - if v.ProtocolName != want_type.Protocol_name {continue} - - for _,v := range v.Format { - if v.FormatName != want_type.Format_name {continue} - - for _,v := range v.Codec { - if v.CodecName != want_type.Codec_name {continue} + no_found_type := true + for { + for _,v := range j.Data.PlayurlInfo.Playurl.Stream { + if v.ProtocolName != want_type.Protocol_name {continue} + + for _,v := range v.Format { + if v.FormatName != want_type.Format_name {continue} + + for _,v := range v.Codec { + if v.CodecName != want_type.Codec_name {continue} + + no_found_type = false - //当前直播流质量 - c.Live_qn = v.CurrentQn - //允许的清晰度 - { - var tmp = make(map[int]string) - for _,v := range v.AcceptQn { - if s,ok := c.AcceptQn[v];ok{ - tmp[v] = s + //当前直播流质量 + c.Live_qn = v.CurrentQn + //允许的清晰度 + { + var tmp = make(map[int]string) + for _,v := range v.AcceptQn { + if s,ok := c.Qn[v];ok{ + tmp[v] = s + } } + c.AcceptQn = tmp + } + //直播流链接 + c.Live = []string{} + for _,v1 := range v.URLInfo { + c.Live = append(c.Live, v1.Host+v.BaseURL+v1.Extra) } - c.AcceptQn = tmp - } - //直播流链接 - c.Live = []string{} - for _,v1 := range v.URLInfo { - c.Live = append(c.Live, v1.Host+v.BaseURL+v1.Extra) } } } + if no_found_type { + if want_type.Protocol_name == "http_stream" { + apilog.L(`I: `, `不支持flv,使用hls`) + want_type = name_map[`hls`] + } else { + apilog.L(`I: `, `不支持hls,使用flv`) + want_type = name_map[`flv`] + } + no_found_type = false + } else { + break + } } - if s,ok := c.AcceptQn[c.Live_qn];!ok{ + if s,ok := c.Qn[c.Live_qn];!ok{ apilog.L(`W: `, `未知清晰度`, c.Live_qn) } else { apilog.L(`I: `, s) diff --git a/Reply/F.go b/Reply/F.go index 3d28df4..10bb722 100644 --- a/Reply/F.go +++ b/Reply/F.go @@ -16,7 +16,7 @@ import ( "net/url" "errors" "bytes" - + c "github.com/qydysky/bili_danmu/CV" F "github.com/qydysky/bili_danmu/F" send "github.com/qydysky/bili_danmu/Send" @@ -241,31 +241,17 @@ func Savestreamf(){ defer savestream.skipFunc.UnSet() } - qn, ok := c.K_v.LoadV("直播流清晰度").(float64) - if !ok || qn < 0 {return} + want_qn, ok := c.K_v.LoadV("直播流清晰度").(float64) + if !ok || want_qn < 0 {return} + c.Live_want_qn = int(want_qn) - { - AcceptQn := []int{} - for k,_ := range c.AcceptQn { - if k <= int(qn) {AcceptQn = append(AcceptQn, k)} - } - MaxQn := 0 - for i:=0; len(AcceptQn)>i; i+=1{ - if AcceptQn[i] > MaxQn { - MaxQn = AcceptQn[i] - } - } - if MaxQn == 0 { - l.L(`W: `,"使用默认清晰度") - } - c.Live_qn = MaxQn - } + F.Get(`Live`) if savestream.cancel.Islive() {return} var ( no_found_link = errors.New("no_found_link") - hls_get_link = func(m3u8_url,last_download string) (need_download []string,m3u8_file_addition []byte,expires int,err error) { + hls_get_link = func(m3u8_url,last_download string) (need_download [][]string,m3u8_file_addition []byte,expires int,err error) { url_struct,e := url.Parse(m3u8_url) if e != nil { err = e @@ -277,9 +263,9 @@ func Savestreamf(){ r := reqf.Req() if e := r.Reqf(reqf.Rval{ Url:m3u8_url, - Retry:2, + Retry:4, SleepTime:1, - Timeout:4, + Timeout:3, Header:map[string]string{ `Host`: url_struct.Host, `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`, @@ -340,7 +326,7 @@ func Savestreamf(){ if last_download == "" { m3u8_file_addition = r.Respon for i:=0;i= c.Live_qn { + expires = int64(exp) + } + + //use guess + if last_download[1] != "" { + previou,_ := strconv.Atoi(last_download[1][:len(last_download[1])-4]) + now,_ := strconv.Atoi(links_and_Base[0][1][:len(links_and_Base[0][1])-4]) + if previou != now-1 { + if diff := now - previou;diff > 15 { + l.L(`W: `,`diff too large `,diff) + break + } else { + l.L(`I: `,`猜测hls`,previou,`-`,now,`(`,diff,`)`) + } + + {//file_add + for i:=now-1;i>previou;i-=1 { + file_add = append([]byte(strconv.Itoa(i)+".m4s"),file_add...) + } + } + {//links_and_Base + if path_front == "" || path_behind == "" { + u, e := url.Parse(links_and_Base[0][0]) + if e != nil { + l.L(`E: `,`fault to enable guess`,e) + return + } + path_front = u.Scheme+"://"+path.Dir(u.Host+u.Path)+"/" + path_behind = "?"+u.RawQuery + } + for i:=now-1;i>previou;i-=1 { + base := strconv.Itoa(i)+".m4s" + links_and_Base = append([][]string{[]string{ + path_front+base+path_behind, + base}},links_and_Base...) + } + } + } + } + f := p.File() f.FileWR(p.Filel{ File:savestream.path+"0.m3u8.dtmp", @@ -479,31 +538,32 @@ func Savestreamf(){ Context:[]interface{}{file_add}, }) - for i:=0;i int64(expires+60) { + if p.Sys().GetSTime()+60 > expires { F.Get(`Liveing`) if !c.Liveing {break} F.Get(`Live`) if len(c.Live)==0 {break} + + // no expect qn + if c.Live_want_qn < c.Live_qn { + expires = time.Now().Add(time.Minute*2).Unix() + } } else { time.Sleep(time.Second) } @@ -545,8 +605,6 @@ func Savestreamf(){ //å·²func形式调用,将会停止保存直播流 func Savestream_wait(){ if !savestream.cancel.Islive() {return} - // qn, ok := c.K_v.LoadV("flv直播流清晰度").(float64) - // if !ok || qn < 0 {return} savestream.cancel.Done() c.Log.Base(`savestream`).L(`I: `,"等待停止") diff --git a/Reply/Msg.go b/Reply/Msg.go index 56f1f93..cbd83fe 100644 --- a/Reply/Msg.go +++ b/Reply/Msg.go @@ -7,13 +7,17 @@ import ( ) /* - 数据为WS_OP_MESSAGE类型的数据分派 + 数据为WS_OP_MESSAGE类型的数据分派https://baidu.com */ var msglog = c.Log.Base(`Msg`) //Msg类型数据处理方法map var Msg_map = map[string]func(replyF, string) { + `PK_LOTTERY_START`:replyF.pk_lottery_start,//大乱斗pk + `PK_BATTLE_PRE_NEW`:nil,//pk准备 + `PK_BATTLE_START_NEW`:nil,//pk开始 + `PK_BATTLE_PROCESS_NEW`:replyF.pk_battle_process_new,//pk进行中 `VTR_GIFT_LOTTERY`:replyF.vtr_gift_lottery,//特别礼物 `ENTRY_EFFECT_MUST_RECEIVE`:nil,//高能榜前三进入 `GIFT_BAG_DOT`:nil, diff --git a/Reply/Reply.go b/Reply/Reply.go index f4e6965..339de48 100644 --- a/Reply/Reply.go +++ b/Reply/Reply.go @@ -66,6 +66,32 @@ func (replyF) defaultMsg(s string){ msglog.Base_add("Unknow").L(`E: `, s) } +//大乱斗pk开始 +func (replyF) pk_lottery_start(s string){ + msglog := msglog.Base_add("大乱斗") + var j ws_msg.PK_LOTTERY_START + if e := json.Unmarshal([]byte(s), &j);e != nil{ + msglog.L(`E: `, e) + return + } + Gui_show(j.Data.Title,`0room`) + msglog.L(`I`, j.Data.Title) +} + +//大乱斗pk状态 +func (replyF) pk_battle_process_new(s string){ + msglog := msglog.Base_add("大乱斗") + var j ws_msg.PK_BATTLE_PROCESS_NEW + if e := json.Unmarshal([]byte(s), &j);e != nil{ + msglog.L(`E: `, e) + return + } + if diff := j.Data.InitInfo.Votes-j.Data.MatchInfo.Votes;diff<0 { + Gui_show(`大乱斗落后`,strconv.Itoa(diff),`0room`) + msglog.L(`I`, `大乱斗落后`,diff) + } +} + //msg-特别礼物 func (replyF) vtr_gift_lottery(s string){ msglog := msglog.Base_add("特别礼物") diff --git a/Reply/ws_msg/PK_BATTLE_PRE_NEW.go b/Reply/ws_msg/PK_BATTLE_PRE_NEW.go new file mode 100644 index 0000000..e243876 --- /dev/null +++ b/Reply/ws_msg/PK_BATTLE_PRE_NEW.go @@ -0,0 +1,21 @@ +package part + +type PK_BATTLE_PRE_NEW struct { + Cmd string `json:"cmd"` + PkStatus int `json:"pk_status"` + PkID int `json:"pk_id"` + Timestamp int `json:"timestamp"` + Data struct { + BattleType int `json:"battle_type"` + MatchType int `json:"match_type"` + Uname string `json:"uname"` + Face string `json:"face"` + UID int `json:"uid"` + RoomID int `json:"room_id"` + SeasonID int `json:"season_id"` + PreTimer int `json:"pre_timer"` + PkVotesName string `json:"pk_votes_name"` + EndWinTask interface{} `json:"end_win_task"` + } `json:"data"` + Roomid int `json:"roomid"` +} \ No newline at end of file diff --git a/Reply/ws_msg/PK_BATTLE_PROCESS_NEW.go b/Reply/ws_msg/PK_BATTLE_PROCESS_NEW.go new file mode 100644 index 0000000..e9a840a --- /dev/null +++ b/Reply/ws_msg/PK_BATTLE_PROCESS_NEW.go @@ -0,0 +1,21 @@ +package part + +type PK_BATTLE_PROCESS_NEW struct { + Cmd string `json:"cmd"` + PkID int `json:"pk_id"` + PkStatus int `json:"pk_status"` + Timestamp int `json:"timestamp"` + Data struct { + BattleType int `json:"battle_type"` + InitInfo struct { + RoomID int `json:"room_id"` + Votes int `json:"votes"` + BestUname string `json:"best_uname"` + } `json:"init_info"` + MatchInfo struct { + RoomID int `json:"room_id"` + Votes int `json:"votes"` + BestUname string `json:"best_uname"` + } `json:"match_info"` + } `json:"data"` +} \ No newline at end of file diff --git a/Reply/ws_msg/PK_BATTLE_START_NEW.go b/Reply/ws_msg/PK_BATTLE_START_NEW.go new file mode 100644 index 0000000..201842f --- /dev/null +++ b/Reply/ws_msg/PK_BATTLE_START_NEW.go @@ -0,0 +1,20 @@ +package part + +type PK_BATTLE_START_NEW struct { + Cmd string `json:"cmd"` + PkID int `json:"pk_id"` + PkStatus int `json:"pk_status"` + Timestamp int `json:"timestamp"` + Data struct { + BattleType int `json:"battle_type"` + FinalHitVotes int `json:"final_hit_votes"` + PkStartTime int `json:"pk_start_time"` + PkFrozenTime int `json:"pk_frozen_time"` + PkEndTime int `json:"pk_end_time"` + PkVotesType int `json:"pk_votes_type"` + PkVotesAdd int `json:"pk_votes_add"` + PkVotesName string `json:"pk_votes_name"` + StarLightMsg string `json:"star_light_msg"` + } `json:"data"` + Roomid string `json:"roomid"` +} \ No newline at end of file diff --git a/Reply/ws_msg/PK_LOTTERY_START.go b/Reply/ws_msg/PK_LOTTERY_START.go new file mode 100644 index 0000000..6b5e10a --- /dev/null +++ b/Reply/ws_msg/PK_LOTTERY_START.go @@ -0,0 +1,23 @@ +package part + +type PK_LOTTERY_START struct { + Cmd string `json:"cmd"` + Data struct { + AssetAnimationPic string `json:"asset_animation_pic"` + AssetIcon string `json:"asset_icon"` + FromUser struct { + Face string `json:"face"` + UID int `json:"uid"` + Uname string `json:"uname"` + } `json:"from_user"` + ID int `json:"id"` + MaxTime int `json:"max_time"` + PkID int `json:"pk_id"` + RoomID int `json:"room_id"` + ThankText string `json:"thank_text"` + Time int `json:"time"` + TimeWait int `json:"time_wait"` + Title string `json:"title"` + Weight int `json:"weight"` + } `json:"data"` +}