"errors"
"fmt"
"io"
- "io/fs"
"math"
"net/http"
"net/http/pprof"
+ "os"
"sort"
"strconv"
"strings"
})
}
+// 录播目录信息
+type paf struct {
+ Uname string `json:"uname"`
+ UpUid int `json:"upUid"`
+ Roomid int `json:"roomid"`
+ Qn string `json:"qn"`
+ Name string `json:"name"`
+ StartT string `json:"start"`
+ Path string `json:"path"`
+}
+
+// 获取录播目录信息
+func getRecInfo(dirpath string) (pathInfo paf, err error) {
+ dirf := file.New(dirpath, 0, true)
+ defer dirf.Close()
+ if dirf.IsDir() {
+ // 从文件夹获取信息
+ {
+ dirfName := dirf.File().Name()
+ pathInfo = paf{Name: dirfName[20:], StartT: dirfName[:19], Path: dirfName}
+ }
+ // 从0.json获取信息
+ {
+ json0 := file.New(dirpath+string(os.PathSeparator)+"0.json", 0, true)
+ defer json0.Close()
+ if data, e := json0.ReadAll(1<<8, 1<<16); e != nil && !errors.Is(e, io.EOF) {
+ err = e
+ return
+ } else {
+ var common c.Common
+ if e := json.Unmarshal(data, &common); e != nil {
+ err = e
+ return
+ } else {
+ pathInfo.Uname = common.Uname
+ pathInfo.UpUid = common.UpUid
+ pathInfo.Roomid = common.Roomid
+ pathInfo.Qn = c.C.Qn[common.Live_qn]
+ pathInfo.Name = common.Title
+ pathInfo.StartT = common.Live_Start_Time.Format(time.DateTime)
+ pathInfo.Path = dirf.File().Name()
+ }
+ }
+ }
+ }
+ return
+}
+
func init() {
flog := flog.Base_add(`直播Web服务`)
if path, ok := c.C.K_v.LoadV(`直播Web服务路径`).(string); ok {
w = cache.Cache(path+"filePath", time.Second*5, w)
if v, ok := c.C.K_v.LoadV(`直播流保存位置`).(string); ok && v != "" {
- type dirEntryDirs []fs.DirEntry
- var list dirEntryDirs
- var err error
- f, err := http.Dir(v).Open("/")
- if err != nil {
- c.ResStruct{Code: -1, Message: err.Error(), Data: nil}.Write(w)
+ dir := file.New(v, 0, true)
+ defer dir.Close()
+ if !dir.IsDir() {
+ c.ResStruct{Code: -1, Message: "not dir", Data: nil}.Write(w)
return
}
- defer f.Close()
- _, err = f.Stat()
- if err != nil {
- c.ResStruct{Code: -1, Message: err.Error(), Data: nil}.Write(w)
- return
- }
- if d, ok := f.(fs.ReadDirFile); ok {
- list, err = d.ReadDir(-1)
- }
+ var filePaths []paf
- if err != nil {
- c.ResStruct{Code: -1, Message: err.Error(), Data: nil}.Write(w)
+ if fs, e := dir.DirFiles(); e != nil {
+ c.ResStruct{Code: -1, Message: e.Error(), Data: nil}.Write(w)
return
- }
-
- type paf struct {
- Name string `json:"name"`
- StartT string `json:"start"`
- Path string `json:"path"`
- }
-
- var filePaths []paf
- for i, n := 0, len(list); i < n; i++ {
- if list[i].IsDir() && len(list[i].Name()) > 20 {
- filePaths = append(filePaths, paf{list[i].Name()[20:], list[i].Name()[:19], list[i].Name()})
+ } else {
+ for i, n := 0, len(fs); i < n; i++ {
+ if filePath, e := getRecInfo((fs[i])); e != nil {
+ c.ResStruct{Code: -1, Message: e.Error(), Data: nil}.Write(w)
+ return
+ } else {
+ filePaths = append(filePaths, filePath)
+ }
}
}
db.Close()
}
}
+
+func Test_getRecInfo(t *testing.T) {
+ pathInfo, err := getRecInfo("testdata/live/2023_06_27-02_17_48-7734200-【预告】27日15点 JDG vs NIP!-原画-YI2")
+ if err != nil {
+ t.Fatal(err)
+ }
+ if pathInfo.Name != "【预告】27日15点 JDG vs NIP!" {
+ t.Fatal()
+ }
+ if pathInfo.Path != "testdata/live/2023_06_27-02_17_48-7734200-【预告】27日15点 JDG vs NIP!-原画-YI2" {
+ t.Fatal()
+ }
+ if pathInfo.Qn != "原画" {
+ t.Fatal()
+ }
+ if pathInfo.StartT != "2023-06-25 15:29:33" {
+ t.Fatal()
+ }
+ if pathInfo.Roomid != 7734200 {
+ t.Fatal()
+ }
+ if pathInfo.UpUid != 50329118 {
+ t.Fatal()
+ }
+}
flog := file.New("0.flv.log", 0, false)
_ = flog.Delete()
defer flog.Close()
- f := file.New("test/0.flv", 0, false)
+ f := file.New("testdata/0.flv", 0, false)
defer f.Close()
if f.IsDir() || !f.IsExist() {
flog := file.New("0.mp4.log", 0, false)
_ = flog.Delete()
defer flog.Close()
- f := file.New("test/0.mp4", 0, false)
+ f := file.New("testdata/0.mp4", 0, false)
defer f.Close()
if f.IsDir() || !f.IsExist() {
"bytes"
"context"
"encoding/base64"
+ "encoding/json"
"errors"
"fmt"
"io"
cr = ms.common.Roomid
)
+ // savestate
+ {
+ fj := file.New(cp+"0.json", 0, true)
+ if common, err := json.Marshal(ms.common); err != nil {
+ l.L(`E: `, err)
+ } else if _, err := fj.Write(common, true); err != nil {
+ l.L(`E: `, err)
+ }
+ fj.Close()
+ }
go StartRecDanmu(contextC, cp+"0.csv") //保存弹幕
go Ass_f(contextC, cp, cp+"0", time.Now()) //开始ass
startT := time.Now()
--- /dev/null
+[Script Info]
+Title: Default Ass file
+ScriptType: v4.00+
+WrapStyle: 0
+ScaledBorderAndShadow: yes
+PlayResX: 720
+PlayResY: 1280
+
+[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,,50,&H40FFFFFF,&H000017FF,&H80000000,&H40000000,0,0,0,0,100,100,0,0,1,4,4,7,20,20,50,1
+
+[Events]
+Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
+Dialogue: 0,0:00:05.07,0:00:12.07,Default,,0,0,0,,{\fad(200,500)\blur3}2
+Dialogue: 0,0:00:15.97,0:00:22.97,Default,,0,0,0,,{\fad(200,500)\blur3}[ίÇü]
+Dialogue: 0,0:00:18.57,0:00:25.57,Default,,0,0,0,,{\fad(200,500)\blur3}1
+Dialogue: 0,0:00:20.00,0:00:27.00,Default,,0,0,0,,{\fad(200,500)\blur3}[Ȭ]
+Dialogue: 0,0:00:22.24,0:00:29.24,Default,,0,0,0,,{\fad(200,500)\blur3}[ÊÖ»ú]
+Dialogue: 0,0:00:36.05,0:00:43.05,Default,,0,0,0,,{\fad(200,500)\blur3}1
+Dialogue: 0,0:00:47.09,0:00:54.09,Default,,0,0,0,,{\fad(200,500)\blur3}11
+Dialogue: 0,0:01:28.47,0:01:35.47,Default,,0,0,0,,{\fad(200,500)\blur3}[ÔÞ]
+Dialogue: 0,0:01:34.62,0:01:41.62,Default,,0,0,0,,{\fad(200,500)\blur3}Ãî°¡
+Dialogue: 0,0:01:35.68,0:01:42.68,Default,,0,0,0,,{\fad(200,500)\blur3}ÀëÆ×
+Dialogue: 0,0:01:36.95,0:01:43.95,Default,,0,0,0,,{\fad(200,500)\blur3}Ó®ÂéÁË
+Dialogue: 0,0:01:38.31,0:01:45.31,Default,,0,0,0,,{\fad(200,500)\blur3}[Ãî]
+Dialogue: 0,0:01:41.65,0:01:48.65,Default,,0,0,0,,{\fad(200,500)\blur3}[Ȭ]
+Dialogue: 0,0:01:47.11,0:01:54.11,Default,,0,0,0,,{\fad(200,500)\blur3}2 x Ãî°¡
+Dialogue: 0,0:01:51.57,0:01:58.57,Default,,0,0,0,,{\fad(200,500)\blur3}1
+Dialogue: 0,0:02:17.43,0:02:24.43,Default,,0,0,0,,{\fad(200,500)\blur3}[±ÈÐÄ]
+Dialogue: 0,0:02:18.79,0:02:25.79,Default,,0,0,0,,{\fad(200,500)\blur3}ºÜÓо«Éñ
+Dialogue: 0,0:02:19.45,0:02:26.45,Default,,0,0,0,,{\fad(200,500)\blur3}[ίÇü]
+Dialogue: 0,0:02:22.53,0:02:29.53,Default,,0,0,0,,{\fad(200,500)\blur3}1
+Dialogue: 0,0:02:31.54,0:02:38.54,Default,,0,0,0,,{\fad(200,500)\blur3}2 x ºÜÓо«Éñ
+Dialogue: 0,0:02:55.48,0:03:02.48,Default,,0,0,0,,{\fad(200,500)\blur3}¨r(£þ¨\8c£þ)¨q.
+Dialogue: 0,0:03:00.41,0:03:07.41,Default,,0,0,0,,{\fad(200,500)\blur3}3
+Dialogue: 0,0:03:03.79,0:03:10.79,Default,,0,0,0,,{\fad(200,500)\blur3}4
+Dialogue: 0,0:03:06.00,0:03:13.00,Default,,0,0,0,,{\fad(200,500)\blur3}2 x 1
+Dialogue: 0,0:03:07.71,0:03:14.71,Default,,0,0,0,,{\fad(200,500)\blur3}5
--- /dev/null
+3.256057,0,{"text":"bili_54521509583: 2","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+15.928122,0,{"text":"我真的超级不想上班: [委屈]","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+17.906624,0,{"text":"你不了解他: 1","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+19.557600,0,{"text":"我真的超级不想上班: [花]","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+21.757359,0,{"text":"我真的超级不想上班: [手机]","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+35.662723,0,{"text":"冷波涟漪: 1","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+45.553203,0,{"text":"Mandatory_Pamper: 11","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+86.899992,0,{"text":"prbf1199: [赞]","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+92.809264,0,{"text":"prbf1199: 妙啊","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+94.459296,0,{"text":"prbf1199: 离谱","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+95.670998,0,{"text":"prbf1199: 赢麻了","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+97.986553,0,{"text":"ydの懿德: [妙]","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+101.400824,0,{"text":"ydの懿德: [花]","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+106.970532,0,{"text":"2 x 妙啊","style":{"color":"","border":false,"mode":0},"time":0}
+111.271901,0,{"text":"冷波涟漪: 1","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+135.720229,0,{"text":"我真的超级不想上班: [比心]","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+136.931505,0,{"text":"白骨擒拿手: 很有精神","style":{"color":"#54eed8","border":false,"mode":0},"time":0}
+138.917025,0,{"text":"我真的超级不想上班: [委屈]","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+141.970612,0,{"text":"ydの懿德: 1","style":{"color":"#ffffff","border":false,"mode":0},"time":0}
+150.970542,0,{"text":"2 x 很有精神","style":{"color":"","border":false,"mode":0},"time":0}
+173.544534,0,{"text":"Mandatory_Pamper: ╮( ̄▽ ̄)╭.","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+179.462505,0,{"text":"从此立志要白嫖: 3","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+182.880179,0,{"text":"从此立志要白嫖: 4","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
+184.970776,0,{"text":"2 x 1","style":{"color":"","border":false,"mode":0},"time":0}
+186.843950,0,{"text":"从此立志要白嫖: 5","style":{"color":"#58c1de","border":false,"mode":0},"time":0}
--- /dev/null
+{
+ "pid": 451081,
+ "liveQn": 10000,
+ "roomid": 7734200,
+ "title": "【预告】27日15点 JDG vs NIP!",
+ "uname": "哔哩哔哩英雄联盟赛事",
+ "upUid": 50329118,
+ "rev": 0,
+ "renqi": 352575,
+ "watched": 0,
+ "onlineNum": 2114,
+ "guardNum": 16,
+ "parentAreaID": 13,
+ "areaID": 561,
+ "locked": false,
+ "note": " -2",
+ "liveStartTime": "2023-06-25T15:29:33Z",
+ "liveing": true,
+ "streamType": {
+ "Protocol_name": "http_stream",
+ "Format_name": "flv",
+ "Codec_name": "avc"
+ },
+ "startT": "2023-06-27T02:16:39.001415551Z"
+}
require (
github.com/gotk3/gotk3 v0.6.2
github.com/mdp/qrterminal/v3 v3.1.1
- github.com/qydysky/part v0.28.1-0.20230622093306-47eb1255c740
+ github.com/qydysky/part v0.28.1-0.20230627085103-b1631761d65e
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
golang.org/x/text v0.10.0
github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/qydysky/part v0.28.1-0.20230622042318-3ef3143a7235 h1:dHloo1tXGDGXynfRsZBb1nQH8hNXWQDzzfc98lsKNaQ=
-github.com/qydysky/part v0.28.1-0.20230622042318-3ef3143a7235/go.mod h1:CdkAHZ+OxieG1sI4M6UowP9j0QQDnhtDtN4tWsylCPU=
-github.com/qydysky/part v0.28.1-0.20230622093306-47eb1255c740 h1:lh0BH3Z5aam1hbf6iEdMsr3YrJAo91d38JgjtE24aJs=
-github.com/qydysky/part v0.28.1-0.20230622093306-47eb1255c740/go.mod h1:CdkAHZ+OxieG1sI4M6UowP9j0QQDnhtDtN4tWsylCPU=
+github.com/qydysky/part v0.28.1-0.20230627085103-b1631761d65e h1:hadrhlWMlfPOD/QN8sA6iUUk/e36MKkO1g5e37+CdBY=
+github.com/qydysky/part v0.28.1-0.20230627085103-b1631761d65e/go.mod h1:CdkAHZ+OxieG1sI4M6UowP9j0QQDnhtDtN4tWsylCPU=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=