diff --git a/config.yml b/config.yml index 69e7a2d..dec4f79 100644 --- a/config.yml +++ b/config.yml @@ -11,8 +11,15 @@ log: feature: use_native_flv_parser: false live_rooms: +# qulity参数目前仅B站启用,默认为0 +# (B站)0代表原画PRO(HEVC)优先, 其他数值为原画(AVC) +# 原画PRO会保存为.ts文件, 原画为.flv +# HEVC相比AVC体积更小, 减少35%体积, 画质相当, 但是B站转码有时候会崩 - url: https://www.lang.live/room/5664344 is_listening: false +- url: https://live.bilibili.com/22603245 + is_listening: true + quality: 0 out_put_tmpl: "" video_split_strategies: on_room_name_changed: false diff --git a/src/cmd/bililive/bililive.go b/src/cmd/bililive/bililive.go index c9c709f..4ec0e5e 100644 --- a/src/cmd/bililive/bililive.go +++ b/src/cmd/bililive/bililive.go @@ -108,6 +108,7 @@ func main() { if v, ok := inst.Config.Cookies[u.Host]; ok { opts = append(opts, live.WithKVStringCookies(u, v)) } + opts = append(opts, live.WithQuality(room.Quality)) l, err := live.New(u, inst.Cache, opts...) if err != nil { logger.WithField("url", room).Error(err.Error()) diff --git a/src/configs/config.go b/src/configs/config.go index 3378021..fcf5c1e 100644 --- a/src/configs/config.go +++ b/src/configs/config.go @@ -83,6 +83,7 @@ type LiveRoom struct { Url string `yaml:"url"` IsListening bool `yaml:"is_listening"` LiveId live.ID `yaml:"-"` + Quality int `yaml:"quality"` } type liveRoomAlias LiveRoom @@ -112,6 +113,7 @@ func NewLiveRoomsWithStrings(strings []string) []LiveRoom { for index, url := range strings { liveRooms[index].Url = url liveRooms[index].IsListening = true + liveRooms[index].Quality = 0 } return liveRooms } diff --git a/src/live/bilibili/bilibili.go b/src/live/bilibili/bilibili.go index 468a22b..809d769 100644 --- a/src/live/bilibili/bilibili.go +++ b/src/live/bilibili/bilibili.go @@ -1,6 +1,7 @@ package bilibili import ( + "fmt" "net/http" "net/url" "strings" @@ -17,10 +18,10 @@ const ( domain = "live.bilibili.com" cnName = "哔哩哔哩" - roomInitUrl = "https://api.live.bilibili.com/room/v1/Room/room_init" - roomApiUrl = "https://api.live.bilibili.com/room/v1/Room/get_info" - userApiUrl = "https://api.live.bilibili.com/live_user/v1/UserInfo/get_anchor_in_room" - liveApiUrl = "https://api.live.bilibili.com/room/v1/Room/playUrl" + roomInitUrl = "https://api.live.bilibili.com/room/v1/Room/room_init" + roomApiUrl = "https://api.live.bilibili.com/room/v1/Room/get_info" + userApiUrl = "https://api.live.bilibili.com/live_user/v1/UserInfo/get_anchor_in_room" + liveApiUrlv2 = "https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo" ) func init() { @@ -134,11 +135,9 @@ func (l *Live) GetStreamUrls() (us []*url.URL, err error) { for _, item := range cookies { cookieKVs[item.Name] = item.Value } - resp, err := requests.Get(liveApiUrl, live.CommonUserAgent, requests.Queries(map[string]string{ - "cid": l.realID, - "quality": "4", - "platform": "web", - }), requests.Cookies(cookieKVs)) + query := fmt.Sprintf("?room_id=%s&protocol=0,1&format=0,1,2&codec=0,1&qn=10000&platform=web&ptype=8&dolby=5&panorama=1", l.realID) + resp, err := requests.Get(liveApiUrlv2+query, live.CommonUserAgent, requests.Cookies(cookieKVs)) + if err != nil { return nil, err } @@ -150,10 +149,23 @@ func (l *Live) GetStreamUrls() (us []*url.URL, err error) { return nil, err } urls := make([]string, 0, 4) - gjson.GetBytes(body, "data.durl.#.url").ForEach(func(_, value gjson.Result) bool { - urls = append(urls, value.String()) + + addr := "" + + if l.Options.Quality == 0 && gjson.GetBytes(body, "data.playurl_info.playurl.stream.1.format.1.codec.#").Int() > 1 { + addr = "data.playurl_info.playurl.stream.1.format.1.codec.1" // hevc m3u8 + } else { + addr = "data.playurl_info.playurl.stream.0.format.0.codec.0" // avc flv + } + + baseURL := gjson.GetBytes(body, addr+".base_url").String() + gjson.GetBytes(body, addr+".url_info").ForEach(func(_, value gjson.Result) bool { + hosts := gjson.Get(value.String(), "host").String() + queries := gjson.Get(value.String(), "extra").String() + urls = append(urls, hosts+baseURL+queries) return true }) + return utils.GenUrls(urls...) } diff --git a/src/live/lives.go b/src/live/lives.go index 5d7d91b..64dbde5 100755 --- a/src/live/lives.go +++ b/src/live/lives.go @@ -31,6 +31,7 @@ type Builder interface { type Options struct { Cookies *cookiejar.Jar + Quality int } func NewOptions(opts ...Option) (*Options, error) { @@ -38,7 +39,7 @@ func NewOptions(opts ...Option) (*Options, error) { if err != nil { return nil, err } - options := &Options{Cookies: cookieJar} + options := &Options{Cookies: cookieJar, Quality: 0} for _, opt := range opts { opt(options) } @@ -72,6 +73,12 @@ func WithKVStringCookies(u *url.URL, cookies string) Option { } } +func WithQuality(quality int) Option { + return func(opts *Options) { + opts.Quality = quality + } +} + type ID string type Live interface { diff --git a/src/pkg/parser/ffmpeg/ffmpeg.go b/src/pkg/parser/ffmpeg/ffmpeg.go index a99b818..a57e2a9 100644 --- a/src/pkg/parser/ffmpeg/ffmpeg.go +++ b/src/pkg/parser/ffmpeg/ffmpeg.go @@ -138,7 +138,6 @@ func (p *Parser) ParseLiveStream(ctx context.Context, url *url.URL, live live.Li "-i", url.String(), "-c", "copy", "-bsf:a", "aac_adtstoasc", - "-f", "flv", file, ) if p.cmdStdIn, err = p.cmd.StdinPipe(); err != nil { diff --git a/src/recorders/recorder.go b/src/recorders/recorder.go index 1882091..a20de11 100644 --- a/src/recorders/recorder.go +++ b/src/recorders/recorder.go @@ -120,6 +120,7 @@ func (r *recorder) tryRecord(ctx context.Context) { tmpl = _tmpl } } + buf := new(bytes.Buffer) if err = tmpl.Execute(buf, info); err != nil { panic(fmt.Sprintf("failed to render filename, err: %v", err)) @@ -127,6 +128,11 @@ func (r *recorder) tryRecord(ctx context.Context) { fileName := filepath.Join(r.OutPutPath, buf.String()) outputPath, _ := filepath.Split(fileName) url := urls[0] + + if strings.Contains(url.Path, "m3u8") { + fileName = fileName[:len(fileName)-4]+".ts" + } + if err = mkdir(outputPath); err != nil { r.getLogger().WithError(err).Errorf("failed to create output path[%s]", outputPath) return