From 52645d55988a02daf3b1de5a0562a0dcfe74067b Mon Sep 17 00:00:00 2001 From: qydysky <32743305+qydysky@users.noreply.github.com> Date: Thu, 13 Oct 2022 01:45:42 +0800 Subject: [PATCH] =?utf8?q?=E7=9B=B4=E6=92=AD=E6=B5=81=E7=B1=BB=E5=9E=8B?= =?utf8?q?=E6=95=85=E9=9A=9C=E5=88=87=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- F/api.go | 14 ++++-- Reply/F.go | 7 +-- Reply/Msg.go | 2 + Reply/Reply.go | 14 ++++++ Reply/stream.go | 91 ++++++++++++++++++++++++++++--------- Reply/ws_msg/LITTLE_TIPS.go | 8 ++++ bili_danmu.go | 9 ++++ demo/config/config_K_v.json | 6 +-- 8 files changed, 117 insertions(+), 34 deletions(-) create mode 100644 Reply/ws_msg/LITTLE_TIPS.go diff --git a/F/api.go b/F/api.go index bdc880d..79ec14a 100644 --- a/F/api.go +++ b/F/api.go @@ -1175,14 +1175,22 @@ func Info(UpUid int) (info J.Info) { //html { + Cookie := make(map[string]string) + c.C.Cookie.Range(func(k, v interface{}) bool { + Cookie[k.(string)] = v.(string) + return true + }) reqi := c.C.ReqPool.Get() defer c.C.ReqPool.Put(reqi) req := reqi.Item.(*reqf.Req) if err := req.Reqf(reqf.Rval{ - Url: `https://api.bilibili.com/x/space/acc/info?mid=` + strconv.Itoa(UpUid) + `&jsonp=jsonp`, + Url: `https://api.bilibili.com/x/space/acc/info?mid=` + strconv.Itoa(UpUid) + `&token=&platform=web&jsonp=jsonp`, Proxy: c.C.Proxy, Timeout: 10 * 1000, Retry: 2, + Header: map[string]string{ + `Cookie`: reqf.Map_2_Cookies_String(Cookie), + }, }); err != nil { apilog.L(`E: `, err) return @@ -1323,9 +1331,7 @@ func (c *GetFunc) Get_cookie() (missKey []string) { WhiteChar: `OO`, }) apilog.L(`W: `, `手机扫命令行二维码登录`) - for _, v := range sys.GetIntranetIp(``) { - apilog.L(`W: `, `或打开链接扫码登录:`, strings.Replace(`http://`+s.Server.Addr+`/qr.png`, `0.0.0.0`, v, -1)) - } + apilog.L(`W: `, `或打开链接扫码登录: http://`+s.Server.Addr+`/qr.png`) sys.Sys().Timeoutf(1) } diff --git a/Reply/F.go b/Reply/F.go index b761c9a..6bbac68 100644 --- a/Reply/F.go +++ b/Reply/F.go @@ -1217,11 +1217,8 @@ func init() { }) c.C.Stream_url = []string{} - for _, v := range sys.GetIntranetIp(``) { - var url = strings.Replace(`http://`+s.Server.Addr, `0.0.0.0`, v, -1) - c.C.Stream_url = append(c.C.Stream_url, url) - flog.L(`I: `, `启动于`, url) - } + c.C.Stream_url = append(c.C.Stream_url, `http://`+s.Server.Addr) + flog.L(`I: `, `启动于 http://`+s.Server.Addr) } } diff --git a/Reply/Msg.go b/Reply/Msg.go index 819fd95..317c00d 100644 --- a/Reply/Msg.go +++ b/Reply/Msg.go @@ -107,6 +107,8 @@ var Msg_map = map[string]func(replyF, string){ "GUARD_HONOR_THOUSAND": nil, "LIKE_INFO_V3_CLICK": replyF.like_info_v3_click, //为主播点赞了 "LIKE_INFO_V3_UPDATE": nil, //为主播点赞了总个数 + "USER_TASK_PROGRESS": nil, + "LITTLE_TIPS": replyF.little_tips, //小提示窗口 } // 屏蔽不需要的消息 diff --git a/Reply/Reply.go b/Reply/Reply.go index d39ac83..a05b2e1 100644 --- a/Reply/Reply.go +++ b/Reply/Reply.go @@ -501,6 +501,20 @@ func (replyF) like_info_v3_click(s string) { msglog.Base_add("房").L(`I: `, s) } +// Msg-小提示窗口 +func (replyF) little_tips(s string) { + var type_item ws_msg.LITTLE_TIPS + + if e := json.Unmarshal([]byte(s), &type_item); e != nil { + msglog.L(`E: `, e) + } + s = type_item.Data.Msg + + Gui_show(s, "0room") + + msglog.Base_add("房").L(`I: `, s) +} + // Msg-开始了视频连线 func (replyF) video_connection_join_start(s string) { msglog := msglog.Base_add("房").Log_show_control(false) diff --git a/Reply/stream.go b/Reply/stream.go index 789d87e..57316ff 100644 --- a/Reply/stream.go +++ b/Reply/stream.go @@ -4,7 +4,9 @@ import ( "bytes" "encoding/base64" "errors" + "fmt" "io" + "math" "net/http" "net/url" "os" @@ -57,10 +59,11 @@ type M4SStream_Config struct { } type m4s_link_item struct { - Url string // m4s链接 - Base string // m4s文件名 - status int // 下载状态 0:未下载 1:正在下载 2:下载完成 3:下载失败 - data []byte // 下载的数据 + Url string // m4s链接 + Base string // m4s文件名 + status int // 下载状态 0:未下载 1:正在下载 2:下载完成 3:下载失败 + data []byte // 下载的数据 + createdTime time.Time //创建时间 } func (t *m4s_link_item) isInit() bool { @@ -262,6 +265,7 @@ func (t *M4SStream) fetchParseM3U8() (m4s_links []*m4s_link_item, m3u8_addon []b } // 解析m3u8 + var tmp []*m4s_link_item for _, line := range bytes.Split(m3u8_respon, []byte("\n")) { if len(line) == 0 { continue @@ -304,12 +308,26 @@ func (t *M4SStream) fetchParseM3U8() (m4s_links []*m4s_link_item, m3u8_addon []b } //将切片添加到返回切片数组 - m4s_links = append(m4s_links, &m4s_link_item{ - Url: m3u8_url.ResolveReference(u).String(), - Base: m4s_link, + tmp = append(tmp, &m4s_link_item{ + Url: m3u8_url.ResolveReference(u).String(), + Base: m4s_link, + createdTime: time.Now(), }) } + // 检查是否服务器发生故障,产出多个切片 + if t.last_m4s != nil { + timed := tmp[len(tmp)-1].createdTime.Sub(t.last_m4s.createdTime).Seconds() + nos, _ := tmp[len(tmp)-1].getNo() + noe, _ := t.last_m4s.getNo() + if math.Abs(timed-float64(nos-noe)) > 2 { + e = fmt.Errorf("服务器 %s 发生故障 %d 秒产出了 %d 切片", m3u8_url.Host, int(timed), nos-noe) + continue + } + } + + m4s_links = append(m4s_links, tmp...) + // 设置最后的切片 defer func(last_m4s *m4s_link_item) { t.last_m4s = last_m4s @@ -390,14 +408,14 @@ func (t *M4SStream) fetchParseM3U8() (m4s_links []*m4s_link_item, m3u8_addon []b } // 请求解析成功,退出获取循环 - break + return } - e = nil + e = errors.New("未能找到可用流服务器") return } -func (t *M4SStream) saveStream() { +func (t *M4SStream) saveStream() (e error) { // 设置保存路径 t.Current_save_path = t.config.save_path + "/" + time.Now().Format("2006_01_02_15_04_05_000") + "_" + strconv.Itoa(t.common.Roomid) + `/` @@ -422,15 +440,18 @@ func (t *M4SStream) saveStream() { switch t.stream_type { case `m3u8`: case `mp4`: - t.saveStreamM4s() + e = t.saveStreamM4s() case `flv`: - t.saveStreamFlv() + e = t.saveStreamFlv() default: - t.log.L(`E: `, `undefind stream type`) + e = errors.New("undefind stream type") + t.log.L(`E: `, e) } + + return } -func (t *M4SStream) saveStreamFlv() { +func (t *M4SStream) saveStreamFlv() (e error) { //对每个直播流进行尝试 for _, v := range t.common.Live { //结束退出 @@ -441,6 +462,7 @@ func (t *M4SStream) saveStreamFlv() { surl, err := url.Parse(v) if err != nil { t.log.L(`E: `, err) + e = err break } @@ -516,7 +538,7 @@ func (t *M4SStream) saveStreamFlv() { return true }) - if e := r.Reqf(reqf.Rval{ + if err := r.Reqf(reqf.Rval{ Url: surl.String(), SaveToPipeWriter: rw, NoResponse: true, @@ -533,20 +555,24 @@ func (t *M4SStream) saveStreamFlv() { `Referer`: "https://live.bilibili.com/", `Cookie`: reqf.Map_2_Cookies_String(CookieM), }, - }); e != nil && !errors.Is(e, io.EOF) { - if reqf.IsCancel(e) { + }); err != nil && !errors.Is(err, io.EOF) { + if reqf.IsCancel(err) { t.log.L(`I: `, `flv下载停止`) - } else if !reqf.IsTimeout(e) { - t.log.L(`E: `, `flv下载失败:`, e) + } else if !reqf.IsTimeout(err) { + e = err + t.log.L(`E: `, `flv下载失败:`, err) } } s.Done() } t.reqPool.Put(req) } + + e = errors.New("未能找到可用流服务器") + return } -func (t *M4SStream) saveStreamM4s() { +func (t *M4SStream) saveStreamM4s() (e error) { // 同时下载数限制 var download_limit = &funcCtrl.BlockFuncN{ Max: 3, @@ -662,7 +688,8 @@ func (t *M4SStream) saveStreamM4s() { if !t.Status.Islive() { if len(download_seq) != 0 { if time.Now().Unix() > t.stream_last_modified.Unix()+300 { - t.log.L(`E: `, `切片下载超时`) + e = errors.New("切片下载超时") + t.log.L(`E: `, e) } else { t.log.L(`I: `, `下载最后切片:`, len(download_seq)) continue @@ -690,6 +717,7 @@ func (t *M4SStream) saveStreamM4s() { continue } if !reqf.IsTimeout(err) { + e = err break } } @@ -726,6 +754,8 @@ func (t *M4SStream) saveStreamM4s() { p.FileMove(t.Current_save_path+"0.m3u8.dtmp", t.Current_save_path+"0.m3u8") } } + + return } func (t *M4SStream) Start() bool { @@ -794,7 +824,24 @@ func (t *M4SStream) Start() bool { } // 保存流 - t.saveStream() + err := t.saveStream() + + // 直播流类型故障切换 + if v, ok := t.common.K_v.LoadV(`直播流类型故障切换`).(bool); v && ok { + if err != nil && err.Error() == "未能找到可用流服务器" { + if v, ok := t.common.K_v.LoadV(`直播流类型`).(string); ok { + switch v { + case "hls": + t.common.K_v.Store(`直播流类型`, `flv`) + case "flv": + t.common.K_v.Store(`直播流类型`, `hls`) + default: + t.log.L(`E: `, `未知的流类型:`+v) + } + } + } + } + } t.log.L(`I: `, `结束录制(`+strconv.Itoa(t.common.Roomid)+`)`) diff --git a/Reply/ws_msg/LITTLE_TIPS.go b/Reply/ws_msg/LITTLE_TIPS.go new file mode 100644 index 0000000..33079a8 --- /dev/null +++ b/Reply/ws_msg/LITTLE_TIPS.go @@ -0,0 +1,8 @@ +package part + +type LITTLE_TIPS struct { + Cmd string `json:"cmd"` + Data struct { + Msg string `json:"msg"` + } `json:"data"` +} diff --git a/bili_danmu.go b/bili_danmu.go index 7454f28..15b056f 100644 --- a/bili_danmu.go +++ b/bili_danmu.go @@ -52,6 +52,15 @@ func Start(roomid ...int) { os.Exit(1) }() + //启动时显示ip + { + if v, ok := c.C.K_v.LoadV("启动时显示ip").(bool); ok && v { + for _, v := range sys.GetIntranetIp(``) { + danmulog.L(`I: `, `当前ip:http://`+v) + } + } + } + { var groomid = flag.Int("r", 0, "roomid") flag.Parse() diff --git a/demo/config/config_K_v.json b/demo/config/config_K_v.json index 1073c98..00346fc 100644 --- a/demo/config/config_K_v.json +++ b/demo/config/config_K_v.json @@ -55,8 +55,7 @@ "直播流清晰度-help": "清晰度可选-1:不保存 0:默认 10000:原画 800:4K 401:蓝光(杜比) 400:蓝光 250:超清 150:高清 80:流畅,无提供所选清晰度时,使用低一档清晰度", "直播流清晰度": 10000, "直播流类型-help": "flv or hls", - "直播流类型": "flv", - "直播流保存位置": "./live", + "直播流类型故障切换": true, "直播hls流均衡-help":"true:使用所有hls服务器", "直播hls流均衡": true, "直播hls流保存为MP4": true, @@ -91,5 +90,6 @@ "扫码登录自动打开标签页": false, "网络中断不退出": true, "http代理地址-help":"例http://127.0.0.1:38223 为空时不使用", - "http代理地址":"" + "http代理地址":"", + "启动时显示ip":true } \ No newline at end of file -- 2.39.2