]> 127.0.0.1 Git - bili_danmu/.git/commitdiff
Add 修改Ass生成 (#171)
authorqydysky <qydysky@foxmail.com>
Sun, 23 Feb 2025 18:30:06 +0000 (02:30 +0800)
committerGitHub <noreply@github.com>
Sun, 23 Feb 2025 18:30:06 +0000 (02:30 +0800)
* Add 修改Ass生成

* Fix ci

12 files changed:
CV/Var.go
F/api.go
README.md
Reply/F.go
Reply/F/ass/ass.go
Reply/F/ass/ass_test.go [new file with mode: 0644]
Reply/F/ass/testdata/0.csv [new file with mode: 0644]
Reply/F/comp.go
Reply/Reply.go
Reply/stream.go
bili_danmu.go
demo/config/config_K_v.json

index ea42f7dd889b95f2332281ab10af3a3754b2a3fd..dea298425a92774ebba831ef3a5f50ddb6d6fc6b 100644 (file)
--- a/CV/Var.go
+++ b/CV/Var.go
@@ -50,6 +50,7 @@ type Common struct {
        PID               int            `json:"-"`                //进程id
        Version           string         `json:"-"`                //版本
        Uid               int            `json:"-"`                //client uid
+       Login             bool           `json:"login"`            //登陆
        Live              []*LiveQn      `json:"live"`             //直播流链接
        Live_qn           int            `json:"liveQn"`           //当前直播流质量
        Live_want_qn      int            `json:"-"`                //期望直播流质量
@@ -104,6 +105,7 @@ func (t *Common) MarshalJSON() ([]byte, error) {
                ParentAreaID  int
                AreaID        int
                Locked        bool
+               Login         bool
                Note          string
                LiveStartTime string
                Liveing       bool
@@ -120,6 +122,7 @@ func (t *Common) MarshalJSON() ([]byte, error) {
                ParentAreaID:  t.ParentAreaID,
                AreaID:        t.AreaID,
                Locked:        t.Locked,
+               Login:         t.Login,
                Note:          t.Note,
                LiveStartTime: t.Live_Start_Time.Format(time.DateTime),
                Liveing:       t.Liveing,
@@ -196,6 +199,7 @@ func (t *Common) IsOn(key string) bool {
 
 func (t *Common) Copy() *Common {
        var c = Common{
+               Login:             t.Login,
                InIdle:            t.InIdle,
                PID:               t.PID,
                Version:           t.Version,
index d9b5826aaa0d00dfb5a52e5d6be4ab323c49119f..fc9acd2b29a839764b75426c6042c682dd48275c 100644 (file)
--- a/F/api.go
+++ b/F/api.go
@@ -947,6 +947,7 @@ func (t *GetFunc) Get_cookie() (missKey []string) {
                                                }
                                        }
 
+                                       t.Login = true
                                        apilog.L(`I: `, `已登录`)
                                        return
                                }
@@ -954,6 +955,7 @@ func (t *GetFunc) Get_cookie() (missKey []string) {
                }
        }
 
+       t.Login = false
        t.Uid = 0
        apilog.L(`I: `, `未登录`)
 
index f665ec50cae8847f3779981a94baada8a7739443..539efb6dddf8f730ecf5b22c3e558bf908799ec2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -679,10 +679,37 @@ I: 2022/09/15 02:23:23 Msg [qydysky丶 : 赞]
 
 当所选类型在当前直播中不可用时,会按以下顺序[`fmp4`,`flv`]尝试。
 
-ass编码GB18030支持中文
+~~ass编码GB18030支持中文~~
 
-- `GB18030`(默认)
-- `utf-8`
+~~- `GB18030`(默认)~~
+~~- `utf-8`~~
+
+Ass默认`utf-8`编码,在录播结束时生成,可以配合`指定房间录制回调`生成硬编码弹幕的视频,配置项如下(>v0.15.9)
+
+```json
+{
+  "指定房间录制回调":[
+    {
+      "roomid-help":"0替换为指定的房间号",
+      "roomid":0,
+      "durationS":10,
+      "after":["ffmpeg","-i","0.{type}","-y","-vf","ass=0.ass","1.{type}"]
+    }
+  ],
+  "Ass": {
+    "fontname-help":"指定字体",
+    "fontname":"",
+    "fontsize-help":"字体大小int",
+    "fontsize":40,
+    "showSec-help":"弹幕显示时长int,秒",
+    "showSec":10,
+    "area-help":"弹幕显示区域,float64,0-1(全屏)",
+    "area":1.0,
+    "alpha-help":"弹幕透明度,float64,0(不透明)-1(透明)",
+    "alpha":1.0
+  }
+}
+```
 
 弹幕回放(仅直播流Web服务)
 
index 77559e30ac14ea83d266637b2fd3e1edb501214e..ae43844c781b719f544d4242326491e2ce3bcdd9 100644 (file)
@@ -1334,10 +1334,6 @@ func init() {
                                        if !file.New(v+"0.csv", 0, true).CheckRoot(s).IsExist() {
                                                w.WriteHeader(http.StatusNotFound)
                                                return
-                                       } else if !file.New(v+"0.xml", 0, true).CheckRoot(s).IsExist() {
-                                               if _, e := danmuXml.DanmuXml.Run(context.Background(), &v); e != nil {
-                                                       flog.L(`E: `, e)
-                                               }
                                        }
 
                                        if s, closeF := PlayRecDanmu(v + "0.csv"); s == nil {
index c048fcf450a4291eac22b04e472d1592b9ce23c4..74deb7aa6d30902251611e30cf2131e5f7b0562c 100644 (file)
 package ass
 
 import (
-       "context"
+       "bytes"
+       "encoding/json"
        "fmt"
+       "iter"
        "math"
        "strconv"
-       "time"
+       "unicode/utf8"
 
-       p "github.com/qydysky/part"
+       "github.com/dustin/go-humanize"
        comp "github.com/qydysky/part/component2"
-       pctx "github.com/qydysky/part/ctx"
        file "github.com/qydysky/part/file"
-       encoder "golang.org/x/text/encoding"
-       "golang.org/x/text/encoding/simplifiedchinese"
+)
+
+var (
+       playResX = 1280 //字幕宽度
+       playResY = 720  //字幕高度
 )
 
 type i interface {
-       Assf(s string) error
-       Ass_f(ctx context.Context, enc, savePath string, st time.Time)
+       ToAss(savePath string)
+       Init(cfg any)
 }
 
 func init() {
-       if e := comp.Register[i]("ass", &Ass{header: Ass_header}); e != nil {
+       if e := comp.Register[i]("ass", &Ass{
+               fontsize: 40,
+               showSec:  10,
+               area:     1.0,
+               alpha:    0,
+               header: `[Script Info]
+Title: Default Ass file
+ScriptType: v4.00+
+WrapStyle: 0
+ScaledBorderAndShadow: yes
+PlayResX: ` + strconv.Itoa(playResX) + `
+PlayResY: ` + strconv.Itoa(playResY) + `
+
+[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,,40,&H40FFFFFF,&H000017FF,&H80000000,&H40000000,0,0,0,0,100,100,0,0,1,1,0,7,20,20,50,1
+
+[Events]
+Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
+`,
+       }); e != nil {
                panic(e)
        }
 }
 
-var (
-       Ass_height = 720  //字幕高度
-       Ass_width  = 1280 //字幕宽度
-       Ass_font   = 50   //字幕字体大小
-       Ass_T      = 7    //单条字幕显示时间
-       Ass_loc    = 7    //字幕位置 小键盘对应的位置
-       accept     = map[string]encoder.Encoding{
-               ``:        simplifiedchinese.GB18030,
-               `GB18030`: simplifiedchinese.GB18030,
-               `utf-8`:   nil,
-       }
-       Ass_header = `[Script Info]
-       Title: Default Ass file
-       ScriptType: v4.00+
-       WrapStyle: 0
-       ScaledBorderAndShadow: yes
-       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) + `,&H40FFFFFF,&H000017FF,&H80000000,&H40000000,0,0,0,0,100,100,0,0,1,4,4,` + strconv.Itoa(Ass_loc) + `,20,20,50,1
-       
-       [Events]
-       Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
-       `
-)
-
 // Ass 弹幕转字幕
 type Ass struct {
-       savePath string           //弹幕ass文件名
-       startT   time.Time        //开始记录的基准时间
-       header   string           //ass开头
-       wrap     encoder.Encoding //编码
+       showSec, fontsize int
+       area              float64
+       alpha             int
+       header            string //ass开头
 }
 
-func (t *Ass) Assf(s string) error {
-       if t.savePath == "" || s == "" {
-               return nil
+func (t *Ass) Init(cfg any) {
+       if c, ok := cfg.(map[string]any); !ok {
+               return
+       } else {
+               fontname := c[`fontname`].(string)
+               if tmp, ok := c[`fontsize`].(float64); ok && tmp > 0 {
+                       t.fontsize = int(tmp)
+               }
+               if tmp, ok := c[`showSec`].(float64); ok && tmp > 0 {
+                       t.showSec = int(tmp)
+               }
+               if tmp, ok := c[`area`].(float64); ok && tmp >= 0 {
+                       t.area = tmp
+               }
+               if tmp, ok := c[`alpha`].(float64); ok && tmp >= 0 {
+                       t.alpha = int(tmp * 255)
+               }
+               t.header = `[Script Info]
+Title: Default Ass file
+ScriptType: v4.00+
+WrapStyle: 0
+ScaledBorderAndShadow: yes
+PlayResX: ` + strconv.Itoa(playResX) + `
+PlayResY: ` + strconv.Itoa(playResY) + `
+
+[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,` + fontname + `,` + strconv.Itoa(t.fontsize) + `,&H40FFFFFF,&H000017FF,&H80000000,&H40000000,0,0,0,0,100,100,0,0,1,1,0,7,20,20,50,1
+
+[Events]
+Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
+`
        }
+}
 
-       st := time.Since(t.startT) + time.Duration(p.Rand().MixRandom(0, 2000))*time.Millisecond
-       et := st + time.Duration(Ass_T)*time.Second
-
-       var b string
-       // b += "Comment: " + strconv.Itoa(loc) + " "+ Dtos(showedt) + "\n"
-       b += `Dialogue: 0,`
-       b += dtos(st) + `,` + dtos(et)
-       b += `,Default,,0,0,0,,{\fad(200,500)\blur3}` + s + "\n"
-
-       f := file.New(t.savePath+"0.ass", -1, true)
-       f.Config.Coder = t.wrap
-       if _, e := f.Write([]byte(b), true); e != nil {
-               return e
+func (t *Ass) ToAss(savePath string) {
+       f := file.New(savePath+"0.ass", 0, false)
+       defer f.Close()
+       if f.IsExist() {
+               _ = f.Delete()
        }
-       return nil
-}
 
-func (t *Ass) Ass_f(ctx context.Context, enc, savePath string, st time.Time) {
-       if v1, ok := accept[enc]; ok {
-               t.wrap = v1
+       lsSize := int(float64(playResY) * t.area / float64(t.fontsize))
+       var lsd = make([]float64, lsSize)
+       var lso = make([]float64, lsSize)
+
+       var write bool
+       for line := range loadCsv(savePath) {
+               if !write {
+                       _, _ = f.Write([]byte(t.header), true)
+                       write = true
+               }
+
+               danmul := utf8.RuneCountInString(line.Text)
+               danmuSec := (float64(t.showSec*t.fontsize*danmul) / float64(t.fontsize*danmul+playResX))
+
+               c := -1
+
+               for i := 0; i < lsSize; i++ {
+                       if lsd[i] > line.Time+float64(t.showSec)-danmuSec {
+                               continue
+                       }
+                       if lso[i] > line.Time {
+                               continue
+                       }
+                       {
+                               lsd[i] = line.Time + float64(t.showSec) //line.Time + (float64(showSec*fontsize*danmul) / float64(fontsize*danmul+playResX))
+                               lso[i] = line.Time + +danmuSec
+                               c = i
+                               break
+                       }
+               }
+
+               if c == -1 {
+                       continue
+               }
+
+               _, _ = f.Write([]byte(
+                       `Dialogue: 0,`+
+                               stos(line.Time)+`,`+stos(line.Time+float64(t.showSec))+
+                               `,Default,,0,0,0,,{`+
+                               `\c&H`+line.Style.Color[5:7]+line.Style.Color[3:5]+line.Style.Color[1:3]+`&`+
+                               `\alpha&H`+fmt.Sprintf("%02x", t.alpha)+`&`+
+                               `\move(`+strconv.Itoa(playResX)+`,`+strconv.Itoa(c*t.fontsize)+`,-`+strconv.Itoa(t.fontsize*danmul)+`,`+strconv.Itoa(c*t.fontsize)+`)`+
+                               `}`+line.Text+"\n"), true)
        }
+}
 
-       t.savePath = savePath
-       f := &file.File{
-               Config: file.Config{
-                       FilePath:  t.savePath + "0.ass",
-                       AutoClose: true,
-                       Coder:     t.wrap,
-               },
+func loadCsv(savePath string) iter.Seq[Data] {
+       return func(yield func(Data) bool) {
+               csvf := file.New(savePath+"0.csv", 0, false)
+               defer csvf.Close()
+
+               if !csvf.IsExist() {
+                       return
+               }
+
+               var data = Data{}
+               for i := 0; true; i += 1 {
+                       if line, e := csvf.ReadUntil([]byte{'\n'}, humanize.KByte, humanize.MByte); len(line) != 0 {
+                               lined := bytes.SplitN(line, []byte{','}, 3)
+                               if len(lined) == 3 {
+                                       if t, e := strconv.ParseFloat(string(lined[0]), 64); e == nil {
+                                               if e := json.Unmarshal(lined[2], &data); e == nil {
+                                                       data.Time = t
+                                                       if data.Style.Color == "" {
+                                                               data.Style.Color = "#FFFFFF"
+                                                       }
+                                                       if !yield(data) {
+                                                               return
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else if e != nil {
+                               break
+                       }
+               }
        }
-       _, _ = f.Write([]byte(t.header), true)
-       t.startT = st
+}
 
-       ctx, done := pctx.WaitCtx(ctx)
-       defer done()
-       <-ctx.Done()
+type DataStyle struct {
+       Color  string `json:"color"`
+       Border bool   `json:"border"`
+       Mode   int    `json:"mode"`
+}
 
-       t.savePath = ""
+type Data struct {
+       Text  string    `json:"text"`
+       Style DataStyle `json:"style"`
+       Time  float64   `json:"time"`
 }
 
-// 时间转化为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
+func stos(sec float64) string {
+       H := int(math.Floor(sec)) / 3600
+       M := int(math.Floor(sec)) % 3600 / 60
+       S := int(math.Floor(sec)) % 60
+       Ns := int(sec*1000) % 1000 / 10
 
-       return fmt.Sprintf("%d:%02d:%02d.%02d", int(math.Floor(t.Hours())), M, S, Ns)
+       return fmt.Sprintf("%d:%02d:%02d.%02d", H, M, S, Ns)
 }
diff --git a/Reply/F/ass/ass_test.go b/Reply/F/ass/ass_test.go
new file mode 100644 (file)
index 0000000..d8bc7ed
--- /dev/null
@@ -0,0 +1,19 @@
+package ass
+
+import (
+       "testing"
+
+       comp "github.com/qydysky/part/component2"
+)
+
+func TestMain(t *testing.T) {
+       var ass = comp.Get[interface {
+               ToAss(savePath string)
+               Init(cfg any)
+       }](`ass`)
+       ass.ToAss("./testdata/")
+}
+
+func TestStos(t *testing.T) {
+       t.Log(stos(3661))
+}
diff --git a/Reply/F/ass/testdata/0.csv b/Reply/F/ass/testdata/0.csv
new file mode 100644 (file)
index 0000000..58abb8f
--- /dev/null
@@ -0,0 +1,19 @@
+0.906548,0,{"text":"外皮糊层奶油谁不会","style":{"color":"#54eed8","border":false,"mode":0},"time":0}
+1.169517,0,{"text":"我觉得苦甜才是高级的甜味","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+2.488067,0,{"text":"《精美》","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+2.495381,0,{"text":"哈哈哈哈","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+3.778851,0,{"text":"这蛋糕真不行吧","style":{"color":"#455ff6","border":false,"mode":0},"time":0}
+3.784946,0,{"text":"麦芽巧克力蛋糕真的很难","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+4.764952,0,{"text":"一坨","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+6.382001,0,{"text":"这蛋糕配抹茶 不会腻","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+6.385787,0,{"text":"为什么要配主菜,喷的莫名其妙","style":{"color":"#ffed4f","border":false,"mode":0},"time":0}
+8.684833,0,{"text":"棉花糖烤焦了","style":{"color":"#54eed8","border":false,"mode":0},"time":0}
+8.695949,0,{"text":"不是啊 你们看蛋糕和夹心都不塌很厉害的","style":{"color":"#e33fff","border":false,"mode":0},"time":0}
+8.982743,0,{"text":"很难欣赏","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+9.976656,0,{"text":"一层出问题整个都出问题,外面还要淋糖浆","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+11.572514,0,{"text":"不得不承认。她做的甜品都挺丑的。。","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+12.558437,0,{"text":"[青春烟火静态表情包_比心心]","style":{"color":"#e33fff","border":false,"mode":0},"time":0}
+12.566395,0,{"text":"不一定,甜的发齁估计","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+12.876798,0,{"text":"[哈哈room_6154037_73546]","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+12.884833,0,{"text":"巧克力的问题","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+14.168164,0,{"text":"蛋糕店的那些基本很少全部纯手工","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
index eedc547805f130578b0bfde128e2c2ccd5e736d8..4c4d702e43f6592ee2634d1c0b929860157103ba 100644 (file)
@@ -25,8 +25,8 @@ var DanmuCountPerMin = comp.Get[interface {
 }](`danmuCountPerMin`)
 
 var Ass = comp.Get[interface {
-       Assf(s string) error
-       Ass_f(ctx context.Context, enc, savePath string, st time.Time)
+       ToAss(savePath string)
+       Init(cfg any)
 }](`ass`)
 
 var Danmuji = comp.Get[interface {
index a20a0b8d28e48106daecdfab29192c2f6b7a40ab..901913d38a4dedc8b91f27cd2a1af4caa7d13df4 100644 (file)
@@ -346,9 +346,6 @@ func (t replyF) anchor_lot_start(s string) {
                sh = append(sh, J.Data.AwardName, "开始")
        }
 
-       { //额外 ass
-               _ = replyFunc.Ass.Assf(fmt.Sprintln("天选之人", J.Data.AwardName, "开始"))
-       }
        fmt.Println(sh...)
        Gui_show(Itos(sh), `0tianxuan`)
 
@@ -380,9 +377,6 @@ func (t replyF) anchor_lot_award(s string) {
                }
        }
        sh = append(sh, "]")
-       { //额外 ass
-               _ = replyFunc.Ass.Assf(fmt.Sprintln("天选之人", J.Data.AwardName, "结束"))
-       }
        fmt.Println(sh...)
        Gui_show(Itos(sh), `0tianxuan`)
 
@@ -461,7 +455,6 @@ func (t replyF) user_toast_msg(s string) {
                })
        }
        { //额外 ass 私信
-               _ = replyFunc.Ass.Assf(fmt.Sprintln(sh...))
                t.Common.Danmu_Main_mq.Push_tag(`guard_update`, nil) //使用连续付费的新舰长无法区分,刷新舰长数
                if msg := t.Common.K_v.LoadV(`上舰私信`).(string); uid != 0 && msg != "" {
                        t.Common.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
@@ -891,9 +884,6 @@ func (t replyF) send_gift(s string) {
                        },
                })
        }
-       { //额外
-               _ = replyFunc.Ass.Assf(fmt.Sprintln(sh...))
-       }
        fmt.Println("\n====")
        fmt.Println(sh...)
        fmt.Print("====\n\n")
@@ -1051,7 +1041,6 @@ func (t replyF) super_chat_message(s string) {
        fmt.Print("====\n")
 
        { //额外
-               _ = replyFunc.Ass.Assf(fmt.Sprintln(sh...))
                Gui_show(Itos(sh), "0superchat")
                //直播流服务弹幕
                SendStreamWs(Danmu_item{
@@ -1408,8 +1397,6 @@ func Msg_showdanmu(item Danmu_item) {
        }
        //展示
        {
-               //ass
-               _ = replyFunc.Ass.Assf(item.msg)
                //直播流服务弹幕
                SendStreamWs(item)
 
index cc140093d2d73de6ebfb54d7223379d007669b14..8da7e8217bf6b21760e9dc43f8f09bb8b482903b 100644 (file)
@@ -1427,11 +1427,6 @@ func (t *M4SStream) Start() bool {
                                        //保存弹幕
                                        go StartRecDanmu(contextC, ms.GetSavePath())
 
-                                       //ass
-                                       if enc, ok := ms.common.K_v.LoadV("Ass编码").(string); ms.common.IsOn(`生成Ass弹幕`) && ms.common.IsOn(`仅保存当前直播间流`) && ok {
-                                               go replyFunc.Ass.Ass_f(contextC, enc, ms.GetSavePath(), time.Now())
-                                       }
-
                                        path := ms.GetSavePath() + `0.` + ms.GetStreamType()
                                        startT := time.Now()
                                        if e := ms.PusherToFile(contextC, path, startf, stopf); e != nil {
@@ -1439,6 +1434,9 @@ func (t *M4SStream) Start() bool {
                                        }
                                        duration := time.Since(startT)
 
+                                       // Ass
+                                       replyFunc.Ass.ToAss(ms.GetSavePath())
+
                                        //PusherToFile fin genFastSeed
                                        if disableFastSeed, ok := ms.common.K_v.LoadV("禁用快速索引生成").(bool); !ok || !disableFastSeed {
                                                type deal interface {
index 72d344c2196b5df8f7491c98428daee4b95e216f..4ee7288d08fcfcbf47508074d5f46ae2d53f3df8 100644 (file)
@@ -94,6 +94,8 @@ func Start() {
                reply.SaveToJson.Init()
                // 附加功能 保持牌子点亮
                reply.KeepMedalLight(mainCtx, c.C)
+               //ass初始化
+               replyFunc.Ass.Init(c.C.K_v.LoadV("Ass"))
                // 指定房间录制区间
                if _, err := recStartEnd.InitF.Run(mainCtx, c.C); err != nil {
                        danmulog.Base("功能", "指定房间录制区间").L(`E: `, err)
index 1bc55d89dea672a769f5af4285e7714f9bfc8aef..fc20fea396e7593832180fee1aa9bc4a30b2142d 100644 (file)
             "max":-1
         }
     ],
-    "ass-help": "只有保存直播流时才考虑生成ass,ass编码默认GB18030(可选utf-8)",
-    "生成Ass弹幕": true,
-    "Ass编码": "GB18030",
+    "ass-help": "只有保存直播流时才考虑生成ass,ass编码默认utf-8",
+    "Ass": {
+        "fontname-help":"指定字体",
+        "fontname":"",
+        "fontsize-help":"字体大小int",
+        "fontsize":40,
+        "showSec-help":"弹幕显示时长int,秒",
+        "showSec":10,
+        "area-help":"弹幕显示区域,float64,0-1(全屏)",
+        "area":1.0,
+        "alpha-help":"弹幕透明度,float64,0(不透明)-1(透明)",
+        "alpha":0.5
+    },
     "弹幕处理": "",
     "弹幕表情": true,
     "弹幕合并": true,