]> 127.0.0.1 Git - bili_danmu/.git/commitdiff
25
authorqydysky <qydysky@foxmail.com>
Sat, 26 Sep 2020 09:56:48 +0000 (17:56 +0800)
committerqydysky <qydysky@foxmail.com>
Sat, 26 Sep 2020 09:56:48 +0000 (17:56 +0800)
README.md
Reply/F.go
Reply/Heartbeat.go
Reply/Msg.go
Reply/Reply.go
_Screenshot/Screenshot_20200926_173834.png [new file with mode: 0644]

index 02e94e54a499b3e260cf01a3a4697b52b065115d..0c9447fdfb27d07e1d22c44253db83f11a65bdbd 100644 (file)
--- a/README.md
+++ b/README.md
@@ -6,7 +6,17 @@ golang go version go1.15.2 linux/amd64
 显示
 case 后有函数调用的为支持,为nil的为待完善,注释掉的调用为未启用
 
-var Msg_map = map[string]func(replayF, string) {
+//Msg类型数据处理方法map
+var Msg_map = map[string]func(replyF, string) {
+       "PK_BATTLE_PRE":nil,//人气pk
+       "PK_BATTLE_START":nil,//人气pk
+       "PK_BATTLE_PROCESS":nil,//人气pk
+       "PK_BATTLE_END":nil,//人气pk
+       "PK_BATTLE_RANK_CHANGE":nil,//人气pk
+       "PK_BATTLE_SETTLE_USER":nil,//人气pk
+       "PK_BATTLE_SETTLE_V2":nil,//人气pk
+       "PK_BATTLE_SETTLE":nil,//人气pk
+       "SYS_MSG":nil,//系统消息
        "ROOM_SKIN_MSG":nil,
        "GUARD_ACHIEVEMENT_ROOM":nil,
        "ANCHOR_LOT_START":nil,//天选之人开始
@@ -23,23 +33,24 @@ var Msg_map = map[string]func(replayF, string) {
        "HOUR_RANK_AWARDS":nil,
        "ROOM_RANK":nil,
        "ROOM_SHIELD":nil,
-       "USER_TOAST_MSG":nil,
-       "WIN_ACTIVITY":nil,
-       "GUARD_BUY":replayF.guard_buy,//大航海购买
-       "WELCOME_GUARD":replayF.welcome_guard,//大航海进入
-       "DANMU_MSG":replayF.danmu,//弹幕
-       "ROOM_CHANGE":replayF.room_change,//房间信息分区改变
-       "ROOM_SILENT_OFF":replayF.roomsilent,//禁言结束
-       "ROOM_SILENT_ON":replayF.roomsilent,//禁言开始
-       "SEND_GIFT":replayF.send_gift,//礼物
-       "ROOM_BLOCK_MSG":replayF.room_block_msg,//封禁
-       "PREPARING":replayF.preparing,//下播
-       "LIVE":replayF.live,//开播
-       "SUPER_CHAT_MESSAGE":nil,//replayF.super_chat_message,//打赏
-       "SUPER_CHAT_MESSAGE_JPN":replayF.super_chat_message,//打赏
-       "PANEL":replayF.panel,//排行榜
-       "ENTRY_EFFECT":nil,//replayF.entry_effect,//进入特效
-       "ROOM_REAL_TIME_MESSAGE_UPDATE":nil,//replayF.roominfo,//粉丝数
+       "USER_TOAST_MSG":replyF.user_toast_msg,//大航海购买信息
+       "WIN_ACTIVITY":replyF.win_activity,//活动
+       "SPECIAL_GIFT":replyF.special_gift,//节奏风暴
+       "GUARD_BUY":nil,//replyF.guard_buy,//大航海购买
+       "WELCOME_GUARD":replyF.welcome_guard,//大航海进入
+       "DANMU_MSG":replyF.danmu,//弹幕
+       "ROOM_CHANGE":replyF.room_change,//房间信息分区改变
+       "ROOM_SILENT_OFF":replyF.roomsilent,//禁言结束
+       "ROOM_SILENT_ON":replyF.roomsilent,//禁言开始
+       "SEND_GIFT":replyF.send_gift,//礼物
+       "ROOM_BLOCK_MSG":replyF.room_block_msg,//封禁
+       "PREPARING":replyF.preparing,//下播
+       "LIVE":replyF.live,//开播
+       "SUPER_CHAT_MESSAGE":nil,//replyF.super_chat_message,//SC
+       "SUPER_CHAT_MESSAGE_JPN":replyF.super_chat_message,//SC
+       "PANEL":replyF.panel,//排行榜
+       "ENTRY_EFFECT":nil,//replyF.entry_effect,//进入特效
+       "ROOM_REAL_TIME_MESSAGE_UPDATE":nil,//replyF.roominfo,//粉丝数
 }
 ```
 以下内容可能过时,点击查看[当前支持功能](https://github.com/qydysky/bili_danmu/blob/master/Reply/F.go#L16)
@@ -59,6 +70,7 @@ var AllF = map[string]bool{
                obs https://obsproject.com/download
                obs-websocket https://github.com/Palakis/obs-websocket/releases
        */
+       "Ass":true,//Ass弹幕生成,由于时间对应关系,仅开启流保存时生效
        "Autoban":true,//自动封禁(仅提示,未完成)
        "Jiezou":true,//带节奏预警,提示弹幕礼仪
        "Danmuji":true,//反射型弹幕机,回应弹幕
@@ -79,6 +91,7 @@ go run main.go
 go run main.go -r=此处填房间ID
 ```
 以下内容可能过时,以实际运行为准
+- 命令窗口(以下为截取)
 ```
 $ go run main.go 
 输入房间号: 213
@@ -86,18 +99,49 @@ INFO: 2020/09/16 16:48:11 [bili_danmu.go 测试] [连接到房间 213]
 INFO: 2020/09/16 16:48:11 [bili_danmu.go 测试] [连接 wss://tx-sh-live-comet-01.chat.bilibili.com/sub]
 INFO: 2020/09/16 16:48:11 [bili_danmu.go 测试] [已连接到房间 213]
 INFO: 2020/09/16 16:48:11 [bili_danmu.go 测试] [开始心跳]
+```
+```
+//大航海进入
 >>> 欢迎 舰长 茶摊儿在森林喝碗山海 进入直播间
+```
+```
+//普通弹幕
 老鸡捉小鹰
 你快扒拉他
 你这好像是补刀
 吓人
+```
+```
+//礼物
 ====
 孤单猫与淋雨猪 投喂 1314 x 辣条 ( 131400 x 金瓜子 )
 ====
+```
+```
+//同字符串合并
 7 x 原神公测B服冲冲冲
+```
+```
+//同字符忽略
 原神公测B站冲冲冲
 ...B服冲冲冲
-
-ctrl+c退出,日志会同时追加记录到文件danmu.log中(文件记录完整信息,不会减少附加功能作用的弹幕)
 ```
+```
+//SC
+====
+SC:  吹舞火 ¥ 30
+我旁边的一万是幻觉吗?
+私の隣の一万は幻ですか?
+====
+```
+ctrl+c退出,会同时追加记录到文件danmu.log中(文件记录完整信息,不会减少附加功能作用的弹幕)
+- 流保存以及弹幕ass
+```
+结束后会保存为
+房间号_时间.mkv
+房间号_时间.ass
+```
+结束后的文件播放效果(显于左上)
+![](_Screenshot/Screenshot_20200926_173834.png)
+
 更多内容详见注释,如有疑问请发issues,欢迎pr
index cf8a989e05f70083f18ca1f19c1effafc6a6907b..c58e5c53e00b0376b7fe92c8af06904ad31f6338 100644 (file)
@@ -16,6 +16,10 @@ import (
        p "github.com/qydysky/part"
 )
 
+/*
+       F额外功能区
+*/
+
 //功能开关
 var AllF = map[string]bool{
        "Saveflv":true,//保存直播流(仅高清)
@@ -29,7 +33,7 @@ var AllF = map[string]bool{
                obs https://obsproject.com/download
                obs-websocket https://github.com/Palakis/obs-websocket/releases
        */
-       "Ass":true,//Ass弹幕生成
+       "Ass":true,//Ass弹幕生成,由于时间对应关系,仅开启流保存时生效
        "Autoban":true,//自动封禁(仅提示,未完成)
        "Jiezou":true,//带节奏预警,提示弹幕礼仪
        "Danmuji":true,//反射型弹幕机,回应弹幕
@@ -40,13 +44,16 @@ var AllF = map[string]bool{
        "Shortdanmu":true,//上下文相同文字缩减
 }
 
+//功能开关选取函数
 func IsOn(s string) bool {
        if v, ok := AllF[s]; ok && v {
                return true
        }
        return false
 }
-//公共
+
+//字符重复度检查
+//a在buf中出现的字符占a的百分数
 func cross(a string,buf []string) (float32) {
        var s float32
        var matched bool
@@ -62,6 +69,8 @@ func cross(a string,buf []string) (float32) {
        }
        return s / float32(len([]rune(a)))
 }
+
+//在a中仅出现一次出现的字符占a的百分数
 func selfcross(a string) (float32) {
        buf := make(map[rune]bool)
        for _,v := range a {
@@ -71,6 +80,11 @@ func selfcross(a string) (float32) {
        }
        return 1 - float32(len(buf)) / float32(len([]rune(a)))
 }
+
+//在a的每个字符串中
+//出现的字符次数最多的
+//占出现的字符总数的百分数
+//*单字符串中的重复出现计为1次
 func selfcross2(a []string) (float32, string) {
        buf := make(map[rune]float32)
        for _,v := range a {
@@ -92,23 +106,24 @@ func selfcross2(a []string) (float32, string) {
        }
        return max / all, maxS
 }
+
 //功能区
+
+//Ass 弹幕转字幕
 type Ass struct {
        Inuse bool
        
-       file string
-       startT time.Time
-       header string
-       rtb [7]time.Duration//通道是否被字节占用
-       ri int
+       file string//弹幕ass文件名
+       startT time.Time//开始记录的基准时间
+       header string//ass开头
 }
 
 var (
-       Ass_height = 720
-       Ass_width = 1280
-       Ass_font = 50
-       Ass_T = 7
-       Ass_loc = 7//小键盘对应的位置
+       Ass_height = 720//字幕高度
+       Ass_width = 1280//字幕宽度
+       Ass_font = 50//字幕字体大小
+       Ass_T = 7//单条字幕显示时间
+       Ass_loc = 7//å­\97å¹\95ä½\8dç½® å°\8fé\94®ç\9b\98对åº\94ç\9a\84ä½\8dç½®
 )
 
 var ass = Ass {
@@ -129,10 +144,13 @@ Style: Default,,`+strconv.Itoa(Ass_font)+`,&H40FFFFFF,&H000017FF,&H80000000,&H70
 Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
 `,
 }
+
+//设定字幕文件名,为""时停止输出
 func Ass_f(file string){
        ass.file = file
 }
 
+//传入要显示的单条字幕
 func Assf(s string){
        if !ass.Inuse {return}
        if ass.file == "" {return}
@@ -157,7 +175,7 @@ func Assf(s string){
        var b string
        // b += "Comment: " + strconv.Itoa(loc) + " "+ Dtos(showedt) + "\n"
        b += `Dialogue: 0,`
-       b += Dtos(st) + `,` + Dtos(et)
+       b += dtos(st) + `,` + dtos(et)
        b += `,Default,,0,0,0,,{\fad(200,500)\blur3}` + s + "\n"
 
        p.File().FileWR(p.Filel{
@@ -168,7 +186,8 @@ func Assf(s string){
        })
 }
 
-func Dtos(t time.Duration) string {
+//时间转化为0:00:00.00规格字符串
+func dtos(t time.Duration) string {
        M := int(math.Floor(t.Minutes())) % 60
        S := int(math.Floor(t.Seconds())) % 60
        Ns := t.Nanoseconds() / int64(time.Millisecond) % 1000 / 10
@@ -176,6 +195,7 @@ func Dtos(t time.Duration) string {
        return fmt.Sprintf("%d:%02d:%02d.%02d", int(math.Floor(t.Hours())), M, S, Ns)
 }
 
+//直播流保存
 type Saveflv struct {
        Inuse bool
        path string
@@ -187,6 +207,7 @@ var saveflv = Saveflv {
        Inuse:IsOn("Saveflv"),
 }
 
+//已go func形式调用,将会获取直播流
 func Saveflvf(){
        if !saveflv.Inuse {return}
        l := p.Logf().New().Open("danmu.log").Base(-1, "saveflv")
@@ -239,6 +260,7 @@ func Saveflvf(){
        }
 }
 
+//已func形式调用,将会停止保存直播流
 func Saveflv_wait(){
        if !saveflv.Inuse {return}
        saveflv.cancel.Done()
index 6adf67ad5a210c990643e6207bf9b4ae29e1b3e5..f28019af8b253a185163b338baf1cde4c7064557 100644 (file)
@@ -7,11 +7,18 @@ import (
        F "github.com/qydysky/bili_danmu/F"
 )
 
+/*
+       HeartBeat数据分派
+*/
+
 var heartlog = p.Logf().New().Base(-1, "Heart.go").Open("danmu.log").Fileonly(true)
+
+//HeartBeat类型处理方法map
 var Heart_map = map[string]func(replyF, string) {
        "heartbeat":replyF.heartbeat,//人气
 }
 
+//HeartBeat类型,将人气4位byte转为字符串,并送到上述map指定的方法
 func Heart(b []byte){
        s := strconv.Itoa(int(F.Btoi32(b, 0)))
        if F,ok := Heart_map["heartbeat"]; ok {
index 87f94e490d1761ba2fbd091e144d2512456e76de..bf4d56ccd2de6411b215cb9ed677f8715def429f 100644 (file)
@@ -3,11 +3,14 @@ package reply
 import (
        p "github.com/qydysky/part"
 )
+
 /*
-       数据为WS_OP_MESSAGE类型的
+       数据为WS_OP_MESSAGE类型的数据分派
 */
 
 var msglog = p.Logf().New().Base(-1, "Msg.go").Open("danmu.log").Level(1)
+
+//Msg类型数据处理方法map
 var Msg_map = map[string]func(replyF, string) {
        "PK_BATTLE_PRE":nil,//人气pk
        "PK_BATTLE_START":nil,//人气pk
@@ -54,6 +57,8 @@ var Msg_map = map[string]func(replyF, string) {
        "ROOM_REAL_TIME_MESSAGE_UPDATE":nil,//replyF.roominfo,//粉丝数
 }
 
+//Msg类型数据处理方法挑选
+//识别cmd字段类型,查找上述map中设置的方法,并将json转为字符串型传入
 func Msg(b []byte) {
        s := string(b)
        if cmd := p.Json().GetValFromS(s, "cmd");cmd == nil {
index 6a1ee58dcab33d8a82ffe56a5acb3f2f59983b4b..95ae73cd15c3682d340adbab4b8c284b98ca019b 100644 (file)
@@ -14,6 +14,8 @@ import (
 var replylog = p.Logf().New().Open("danmu.log").Base(-1, "Reply.go")
 
 //返回数据分派
+//传入接受到的ws数据
+//判断进行解压,并对每个json对象进行分派
 func Reply(b []byte) {
        replylog.Base(-1, "返回分派")
        defer replylog.Base(0)
@@ -46,12 +48,16 @@ func Reply(b []byte) {
        }
 }
 
+//所有的json对象处理子函数类
+//包含Msg和HeartBeat两大类
 type replyF struct {}
 
+//默认未识别Msg
 func (replyF) defaultMsg(s string){
        msglog.Base(1, "Unknow").E(s)
 }
 
+//msg-通常是大航海购买续费
 func (replyF) user_toast_msg(s string){
        username := p.Json().GetValFromS(s, "data.username");
        op_type := p.Json().GetValFromS(s, "data.op_type");
@@ -97,13 +103,16 @@ func (replyF) user_toast_msg(s string){
 
        msglog.Fileonly(true)
        defer msglog.Fileonly(false)
-       msglog.Base(1, "礼").I(sh...)}
+       msglog.Base(1, "礼").I(sh...)
+}
 
+//HeartBeat-心跳用来传递人气值
 func (replyF) heartbeat(s string){
        if s == "1" {return}//人气为1,不输出
        heartlog.I("当前人气", s)
 }
 
+//Msg-房间特殊活动
 func (replyF) win_activity(s string){
        msglog.Fileonly(true)
        defer msglog.Fileonly(false)
@@ -114,6 +123,7 @@ func (replyF) win_activity(s string){
        msglog.Base(1, "房").I("活动", title, "已开启")
 }
 
+//Msg-特殊礼物,当前仅观察到节奏风暴
 func (replyF) special_gift(s string){
        msglog.Fileonly(true)
        defer msglog.Fileonly(false)
@@ -139,6 +149,7 @@ func (replyF) special_gift(s string){
 
 }
 
+//Msg-大航海购买,由于信息少,用user_toast_msg进行替代
 func (replyF) guard_buy(s string){
        username := p.Json().GetValFromS(s, "data.username");
        gift_name := p.Json().GetValFromS(s, "data.gift_name");
@@ -167,6 +178,7 @@ func (replyF) guard_buy(s string){
        msglog.Base(1, "礼").I(sh...)
 }
 
+//Msg-房间信息改变,标题等
 func (replyF) room_change(s string){
        title := p.Json().GetValFromS(s, "data.title");
        area_name := p.Json().GetValFromS(s, "data.area_name");
@@ -182,6 +194,7 @@ func (replyF) room_change(s string){
        msglog.Base(1, "房").I(sh...)
 }
 
+//Msg-大航海欢迎信息
 func (replyF) welcome_guard(s string){
 
        username := p.Json().GetValFromS(s, "data.username");
@@ -207,6 +220,7 @@ func (replyF) welcome_guard(s string){
        msglog.Base(1, "房").Fileonly(true).I(sh...).Fileonly(false)
 }
 
+//Msg-礼物处理,对于小于30人民币的礼物不显示
 func (replyF) send_gift(s string){
        // coin_type := p.Json().GetValFromS(s, "data.coin_type");
        num := p.Json().GetValFromS(s, "data.num");
@@ -251,6 +265,7 @@ func (replyF) send_gift(s string){
        msglog.Base(1, "礼").I(sh...)
 }
 
+//Msg-房间封禁信息
 func (replyF) room_block_msg(s string) {
        msglog.Fileonly(true)
        defer msglog.Fileonly(false)
@@ -264,6 +279,7 @@ func (replyF) room_block_msg(s string) {
        }
 }
 
+//Msg-房间准备信息,通常出现在下播而不出现在开播
 func (replyF) preparing(s string) {
        msglog.Base(1, "房")
 
@@ -283,6 +299,7 @@ func (replyF) preparing(s string) {
        }
 }
 
+//Msg-房间开播信息
 func (replyF) live(s string) {
        msglog.Base(1, "房")
 
@@ -303,6 +320,7 @@ func (replyF) live(s string) {
        }
 }
 
+//Msg-超级留言处理
 func (replyF) super_chat_message(s string){
        uname := p.Json().GetValFromS(s, "data.user_info.uname");
        price := p.Json().GetValFromS(s, "data.price");
@@ -317,23 +335,25 @@ func (replyF) super_chat_message(s string){
        if price != nil {
                sh = append(sh, "¥", price)
        }
+       fmt.Println("\n====")
+       fmt.Println(sh...)
        if message != nil {
+               fmt.Println(message)
                sh = append(sh, message)
        }
        if message_jpn != nil && message != message_jpn {
+               fmt.Println(message_jpn)
                sh = append(sh, message_jpn)
        }
-       msglog.Fileonly(true)
-       defer msglog.Fileonly(false)
+       fmt.Print("====\n\n")
+       
        {//额外
                Assf(fmt.Sprintln(sh...))
        }
-       fmt.Println("\n====")
-       fmt.Println(sh...)
-       fmt.Print("====\n\n")
-       msglog.Base(1, "礼").I(sh...)
+       msglog.Base(1, "礼").Fileonly(true).I(sh...).Fileonly(false)
 }
 
+//Msg-分区排行
 func (replyF) panel(s string){
        msglog.Fileonly(true).Base(1, "房")
        defer msglog.Fileonly(false)
@@ -347,6 +367,7 @@ func (replyF) panel(s string){
        }
 }
 
+//Msg-进入特效,大多为大航海进入,信息少,使用welcome_guard替代
 func (replyF) entry_effect(s string){
        msglog.Fileonly(true).Base(-1, "房")
        defer msglog.Base(0).Fileonly(false)
@@ -361,6 +382,7 @@ func (replyF) entry_effect(s string){
 
 }
 
+//Msg-房间禁言
 func (replyF) roomsilent(s string){
        msglog.Base(1, "房")
 
@@ -373,6 +395,7 @@ func (replyF) roomsilent(s string){
        }
 }
 
+//Msg-粉丝信息,常刷屏,不显示
 func (replyF) roominfo(s string){
        fans := p.Json().GetValFromS(s, "data.fans");
        fans_club := p.Json().GetValFromS(s, "data.fans_club");
@@ -389,6 +412,7 @@ func (replyF) roominfo(s string){
        if len(sh) != 0 {msglog.Base(1, "粉").I(sh...)}
 }
 
+//Msg-弹幕处理
 func (replyF) danmu(s string) {
        if info := p.Json().GetValFromS(s, "info");info == nil {
                msglog.E("info", info)
@@ -417,11 +441,16 @@ func (replyF) danmu(s string) {
        }
 }
 
+//弹幕发送
+//传入字符串即可发送
+//需要cookie
 func Msg_senddanmu(msg string){
        if c.Cookie == "" || c.Roomid == 0 {return}
        S.Danmu_s(msg, c.Cookie, c.Roomid)
 }
 
+//弹幕显示
+//由于额外功能有些需要显示,为了统一管理,使用此方法进行处理
 func Msg_showdanmu(auth interface{}, msg string) {
        {//附加功能 更少弹幕
                if Lessdanmuf(msg, 20) > 0.7 {//与前20条弹幕重复的字数占比度>0.7的屏蔽
diff --git a/_Screenshot/Screenshot_20200926_173834.png b/_Screenshot/Screenshot_20200926_173834.png
new file mode 100644 (file)
index 0000000..67f289b
Binary files /dev/null and b/_Screenshot/Screenshot_20200926_173834.png differ