From fac9706b8cab149a84e6357b05826442ddc5026a Mon Sep 17 00:00:00 2001 From: qydysky Date: Thu, 24 Sep 2020 20:48:02 +0800 Subject: [PATCH] 22 --- .gitignore | 1 + Const/Var.go | 7 ++++ Reply/F.go | 100 +++++++++++++++++++------------------------------ Reply/Msg.go | 2 - Reply/Reply.go | 18 ++++----- api.go | 99 +++++++++++++++++++++++++++++++++++++++++++++--- bili_danmu.go | 11 ++++-- 7 files changed, 155 insertions(+), 83 deletions(-) create mode 100644 Const/Var.go diff --git a/.gitignore b/.gitignore index f9ebe15..c519d55 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ demo/*.flv demo/*.mp4 demo/*.dtmp demo/*.ass +demo/*.mkv diff --git a/Const/Var.go b/Const/Var.go new file mode 100644 index 0000000..311046e --- /dev/null +++ b/Const/Var.go @@ -0,0 +1,7 @@ +package constf + +var ( + Live string//直播链接 + Roomid int + Cookie string +) \ No newline at end of file diff --git a/Reply/F.go b/Reply/F.go index 111d384..45ac545 100644 --- a/Reply/F.go +++ b/Reply/F.go @@ -9,6 +9,7 @@ import ( "time" "os/exec" + c "github.com/qydysky/bili_danmu/Const" "github.com/christopher-dG/go-obs-websocket" p "github.com/qydysky/part" ) @@ -101,24 +102,26 @@ type Ass struct { } var ( + Ass_height = 720 Ass_width = 1280 - Ass_font = 55 - Ass_move = 13 + Ass_font = 50 + Ass_T = 7 + Ass_loc = 1//小键盘对应的位置 ) var ass = Ass { Inuse:IsOn("Ass"), header:`[Script Info] -Title: Default Aegisub file +Title: Default Ass file ScriptType: v4.00+ WrapStyle: 0 ScaledBorderAndShadow: yes -PlayResX: `+strconv.Itoa(Ass_width/16*9)+` +PlayResX: `+strconv.Itoa(Ass_height)+` PlayResY: `+strconv.Itoa(Ass_width)+` [V4+ Styles] Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding -Style: Default,,`+strconv.Itoa(Ass_font)+`,&H70FFFFFF,&H000017FF,&H80000000,&H89000000,0,0,0,0,100,100,0,0,1,2,0,8,15,15,15,1 +Style: Default,,`+strconv.Itoa(Ass_font)+`,&H60FFFFFF,&H000017FF,&H80000000,&H79000000,0,0,0,0,100,100,0,0,1,1,1,`+strconv.Itoa(Ass_loc)+`,15,15,15,1 [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text @@ -143,30 +146,15 @@ func Assf(s,file string){ } if s == "" {return} - st := time.Since(ass.startT) + time.Duration(p.Rand().MixRandom(0, 2000)) * time.Millisecond - et := st + time.Duration(float64(len([]rune(s)) * Ass_font * Ass_move) / 1000 / 2) * time.Second - loc := -1 - - if ass.ri > 20 {ass.ri = 0} - for k,v := range ass.rtb { - if st > v { - loc = k - ass.rtb[k] = et - break - } - } - switch loc { - case 0:ass.ri += 1 - case -1:return - default: - } + st := time.Since(ass.startT) + time.Duration(p.Rand().MixRandom(0, 2000)) * time.Millisecond + et := st + time.Duration(Ass_T) * time.Second var b string - // b += "Comment: " + Dtos(et) + "\n" - b += `Dialogue: ` + strconv.Itoa(ass.ri) + "," - b += Dtos(st) + `,` + Dtos(et + time.Duration(float64(Ass_width * Ass_move) / 1000) * time.Second) - b += `,Default,,0,0,0,Banner;`+strconv.Itoa(Ass_move)+`[;0;0],` + s + "\n" + // b += "Comment: " + strconv.Itoa(loc) + " "+ Dtos(showedt) + "\n" + b += `Dialogue: 0,` + b += Dtos(st) + `,` + Dtos(et) + b += `,Default,,0,0,0,,{\fad(500,500)\blur3}` + s + "\n" p.File().FileWR(p.Filel{ File:ass.file + ".ass", @@ -200,42 +188,30 @@ func Saveflvf(){ l := p.Logf().New().Open("danmu.log").Base(1, "saveflv") defer l.BC() - r := p.Get(p.Rval{ - Url:"https://live.bilibili.com/" + strconv.Itoa(Msg_roomid), - }) - if e := r.S(`"durl":[`, `]`, 0, 0).Err;e != nil { - return - } else { - if url := p.Json().GetValFromS("[" + r.RS + "]", "[0].url");url == nil { - l.Fileonly(true).E("url", url) - return - } else { - if saveflv.path != "" {return} - saveflv.path = strconv.Itoa(Msg_roomid) + "_" + time.Now().Format(time.RFC3339) - l.I("直播流保存到", saveflv.path) - - saveflv.wait = make(chan bool,1) - saveflv.cancel = make(chan interface{},1) - - Assf("",saveflv.path)//ass - - rr := p.Req() - go func(){ - <- saveflv.cancel - rr.Close() - }() - if e := rr.Reqf(p.Rval{ - Url:url.(string), - Retry:10, - SleepTime:5, - SaveToPath:saveflv.path + ".flv", - Timeout:-1, - }); e != nil{l.E(e)} - Saveflv_transcode() - l.I("结束") - close(saveflv.wait) - } - } + if saveflv.path != "" || c.Live == "" {return} + saveflv.path = strconv.Itoa(c.Roomid) + "_" + time.Now().Format(time.RFC3339) + l.I("直播流保存到", saveflv.path) + + saveflv.wait = make(chan bool,1) + saveflv.cancel = make(chan interface{},1) + + Assf("",saveflv.path)//ass + + rr := p.Req() + go func(){ + <- saveflv.cancel + rr.Close() + }() + if e := rr.Reqf(p.Rval{ + Url:c.Live, + Retry:10, + SleepTime:5, + SaveToPath:saveflv.path + ".flv", + Timeout:-1, + }); e != nil{l.E(e)} + Saveflv_transcode() + l.I("结束") + close(saveflv.wait) } func Saveflv_transcode(){ diff --git a/Reply/Msg.go b/Reply/Msg.go index aa6b6f5..8bd12b4 100644 --- a/Reply/Msg.go +++ b/Reply/Msg.go @@ -8,8 +8,6 @@ import ( */ var msglog = p.Logf().New().Base(-1, "Msg.go").Open("danmu.log").Level(1) -var Msg_cookie string -var Msg_roomid int var Msg_map = map[string]func(replyF, string) { "ROOM_SKIN_MSG":nil, "GUARD_ACHIEVEMENT_ROOM":nil, diff --git a/Reply/Reply.go b/Reply/Reply.go index b7ac64f..8f41844 100644 --- a/Reply/Reply.go +++ b/Reply/Reply.go @@ -8,7 +8,7 @@ import ( p "github.com/qydysky/part" F "github.com/qydysky/bili_danmu/F" S "github.com/qydysky/bili_danmu/Send" - . "github.com/qydysky/bili_danmu/Const" + c "github.com/qydysky/bili_danmu/Const" ) var replylog = p.Logf().New().Open("danmu.log").Base(-1, "Reply.go") @@ -18,10 +18,10 @@ func Reply(b []byte) { replylog.Base(-1, "返回分派") defer replylog.Base(0) - head := F.HeadChe(b[:WS_PACKAGE_HEADER_TOTAL_LENGTH]) + head := F.HeadChe(b[:c.WS_PACKAGE_HEADER_TOTAL_LENGTH]) if int(head.PackL) > len(b) {replylog.E("包缺损");return} - if head.BodyV == WS_BODY_PROTOCOL_VERSION_DEFLATE { + if head.BodyV == c.WS_BODY_PROTOCOL_VERSION_DEFLATE { readc, err := zlib.NewReader(bytes.NewReader(b[16:])) if err != nil {replylog.E("解压错误");return} defer readc.Close() @@ -32,13 +32,13 @@ func Reply(b []byte) { } for len(b) != 0 { - head := F.HeadChe(b[:WS_PACKAGE_HEADER_TOTAL_LENGTH]) + head := F.HeadChe(b[:c.WS_PACKAGE_HEADER_TOTAL_LENGTH]) if int(head.PackL) > len(b) {replylog.E("包缺损");return} - contain := b[WS_PACKAGE_HEADER_TOTAL_LENGTH:head.PackL] + contain := b[c.WS_PACKAGE_HEADER_TOTAL_LENGTH:head.PackL] switch head.OpeaT { - case WS_OP_MESSAGE:Msg(contain) - case WS_OP_HEARTBEAT_REPLY:Heart(contain) + case c.WS_OP_MESSAGE:Msg(contain) + case c.WS_OP_HEARTBEAT_REPLY:Heart(contain) default :replylog.W("unknow reply", contain) } @@ -362,8 +362,8 @@ func (replyF) danmu(s string) { } func Msg_senddanmu(msg string){ - if Msg_cookie == "" || Msg_roomid == 0 {return} - S.Danmu_s(msg, Msg_cookie, Msg_roomid) + if c.Cookie == "" || c.Roomid == 0 {return} + S.Danmu_s(msg, c.Cookie, c.Roomid) } func Msg_showdanmu(auth interface{}, msg string) { diff --git a/api.go b/api.go index f989270..7575612 100644 --- a/api.go +++ b/api.go @@ -10,6 +10,7 @@ type api struct { Roomid int Uid int Url []string + Live string Token string } @@ -42,25 +43,111 @@ func (i *api) Get_info() (o *api) { }) //uid if tmp := r.S(`"uid":`, `,`, 0, 0);tmp.Err != nil { - apilog.E("uid", tmp.Err) - return + // apilog.E("uid", tmp.Err) } else if i,err := strconv.Atoi(tmp.RS); err != nil{ apilog.E("uid", err) - return } else { o.Uid = i } //roomid if tmp := r.S(`"room_id":`, `,`, 0, 0);tmp.Err != nil { - apilog.E("room_id", tmp.Err) - return + // apilog.E("room_id", tmp.Err) } else if i,err := strconv.Atoi(tmp.RS); err != nil{ apilog.E("room_id", err) - return } else { apilog.T("ok") o.Roomid = i } + + if o.Roomid != 0 && o.Uid != 0 {return} + + { + req := p.Req() + if err := req.Reqf(p.Rval{ + Url:"https://api.live.bilibili.com/room/v1/Room/room_init?id=" + Roomid, + Referer:"https://live.bilibili.com/" + Roomid, + Timeout:10, + Retry:2, + });err != nil { + apilog.E(err) + return + } + res := string(req.Respon) + if msg := p.Json().GetValFrom(res, "msg");msg == nil || msg != "ok" { + apilog.E("msg", msg) + return + } + if Uid := p.Json().GetValFrom(res, "data.uid");Uid == nil { + apilog.E("data.uid", Uid) + return + } else { + o.Uid = int(Uid.(float64)) + } + + if room_id := p.Json().GetValFrom(res, "data.room_id");room_id == nil { + apilog.E("data.room_id", room_id) + return + } else { + apilog.T("ok") + o.Roomid = int(room_id.(float64)) + } + } + return +} + +func (i *api) Get_live() (o *api) { + o = i + if o.Roomid == 0 { + apilog.E("还未New_api") + return + } + + {//html获取 + r := p.Get(p.Rval{ + Url:"https://live.bilibili.com/" + strconv.Itoa(o.Roomid), + }) + if e := r.S(`"durl":[`, `]`, 0, 0).Err;e == nil { + if url := p.Json().GetValFromS("[" + r.RS + "]", "[0].url");url == nil { + apilog.E("url", url) + } else { + apilog.T("ok") + o.Live = url.(string) + return + } + } + } + {//api获取 + req := p.Req() + if err := req.Reqf(p.Rval{ + Url:"https://api.live.bilibili.com/xlive/web-room/v1/index/getRoomPlayInfo?play_url=1&mask=1&qn=0&platform=web&ptype=16&room_id=" + strconv.Itoa(o.Roomid), + Referer:"https://live.bilibili.com/" + strconv.Itoa(o.Roomid), + Timeout:10, + Retry:2, + });err != nil { + apilog.E(err) + return + } + res := string(req.Respon) + if code := p.Json().GetValFrom(res, "code");code == nil || code.(float64) != 0 { + apilog.E("code", code) + return + } + if live_status := p.Json().GetValFrom(res, "data.live_status");live_status == nil { + apilog.E("data.live_status", live_status) + return + } else if live_status == 0 {//未直播 + apilog.W("未在直播") + return + } + + if url := p.Json().GetValFrom(res, "data.play_url.durl.[0].url");url == nil { + apilog.E("url", url) + return + } else { + apilog.T("ok") + o.Live = url.(string) + } + } return } diff --git a/bili_danmu.go b/bili_danmu.go index 87de871..7302da7 100644 --- a/bili_danmu.go +++ b/bili_danmu.go @@ -9,6 +9,7 @@ import ( p "github.com/qydysky/part" reply "github.com/qydysky/bili_danmu/Reply" + c "github.com/qydysky/bili_danmu/Const" F "github.com/qydysky/bili_danmu/F" ) @@ -16,6 +17,7 @@ const LogLevel = 1 var danmulog = p.Logf().New().Open("danmu.log").Base(-1, "bili_danmu.go").Level(LogLevel) func Demo() { + danmulog.Base(-1, "测试") defer danmulog.Base(0) @@ -43,7 +45,7 @@ func Demo() { var break_sign bool for !break_sign { //获取房间相关信息 - api := New_api(room).Get_host_Token() + api := New_api(room).Get_host_Token().Get_live() if len(api.Url) == 0 || api.Roomid == 0 || api.Token == "" || api.Uid == 0 { danmulog.E("some err") return @@ -75,9 +77,10 @@ func Demo() { File:"cookie.txt", Write:false, }) - //传输变量至Msg,以便响应弹幕"弹幕机在么" - reply.Msg_roomid = api.Roomid - reply.Msg_cookie = f + //传输变量,以便响应弹幕"弹幕机在么" + c.Roomid = api.Roomid + c.Live = api.Live + c.Cookie = f {//附加功能 弹幕机 直播流保存 reply.Danmuji_auto(1) go reply.Saveflvf() -- 2.39.2