From: qydysky Date: Fri, 17 Jan 2025 18:37:34 +0000 (+0800) Subject: Improve fmp4指向新链接 (#151) X-Git-Tag: v0.15.2~8 X-Git-Url: http://127.0.0.1:8081/?a=commitdiff_plain;h=e0e7523e0b6274a9dc39647687c9105242f47abf;p=bili_danmu%2F.git Improve fmp4指向新链接 (#151) --- diff --git a/.gitignore b/.gitignore index 03bdee3..90e5138 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ demo/qr.png demo/live demo/main.exe *.m4s -*.m3u8 demo/build.bat demo/build.sh Reply/0.flv.log diff --git a/Reply/F/comp.go b/Reply/F/comp.go index 3c4406e..2bbb888 100644 --- a/Reply/F/comp.go +++ b/Reply/F/comp.go @@ -2,6 +2,7 @@ package f import ( "context" + "iter" "net/http" "time" @@ -9,6 +10,7 @@ import ( _ "github.com/qydysky/bili_danmu/Reply/F/danmuCountPerMin" _ "github.com/qydysky/bili_danmu/Reply/F/danmuEmotes" _ "github.com/qydysky/bili_danmu/Reply/F/danmuji" + _ "github.com/qydysky/bili_danmu/Reply/F/parseM3u8" _ "github.com/qydysky/bili_danmu/Reply/F/videoFastSeed" comp "github.com/qydysky/part/component2" log "github.com/qydysky/part/log" @@ -36,6 +38,14 @@ var VideoFastSeed = comp.Get[interface { InitSav(fastSeedFilePath string) (savIndex func(seedTo time.Duration, cuIndex int64) error, e error) }](`videoFastSeed`) +var ParseM3u8 = comp.Get[interface { + Parse(respon []byte, lastNo int) (m4sLink iter.Seq[interface { + IsHeader() bool + M4sLink() string + }], redirectUrl string, err error) + IsErrRedirect(e error) bool +}](`parseM3u8`) + type DanmuEmotesS struct { Logg *log.Log_interface Info []any diff --git a/Reply/F/parseM3u8/parseM3u8.go b/Reply/F/parseM3u8/parseM3u8.go new file mode 100644 index 0000000..93ccf6a --- /dev/null +++ b/Reply/F/parseM3u8/parseM3u8.go @@ -0,0 +1,163 @@ +package parsem3u8 + +import ( + "bytes" + "encoding/base64" + "errors" + "iter" + "strconv" + "strings" + + comp "github.com/qydysky/part/component2" +) + +type TargetInterface interface { + Parse(respon []byte, lastNo int) (m4sLink iter.Seq[interface { + IsHeader() bool + M4sLink() string + }], redirectUrl string, err error) + IsErrRedirect(e error) bool +} + +func init() { + if e := comp.Register[TargetInterface]("parseM3u8", parseM3u8{}); e != nil { + panic(e) + } +} + +var ( + ErrRedirect = errors.New(`ErrRedirect`) + + extXStreamInf = []byte("#EXT-X-STREAM-INF") + extXMap = []byte("#EXT-X-MAP") +) + +type parseM3u8I struct { + link string + header bool +} + +func (t parseM3u8I) IsHeader() bool { return t.header } +func (t parseM3u8I) M4sLink() string { return t.link } + +type parseM3u8 struct{} + +func (t parseM3u8) IsErrRedirect(e error) bool { + return e != nil && errors.Is(e, ErrRedirect) +} + +func (t parseM3u8) Parse(respon []byte, lastNo int) (m4sLink iter.Seq[interface { + IsHeader() bool + M4sLink() string +}], redirectUrl string, err error) { + // base64解码 + if len(respon) != 0 && !bytes.Contains(respon, []byte("#")) { + respon, err = base64.StdEncoding.DecodeString(string(respon)) + if err != nil { + return + } + } + + m3u := bytes.Split(respon, []byte("\n")) + var maxqn int = -1 + for i := 0; i < len(m3u); i++ { + if bytes.HasPrefix(m3u[i], extXStreamInf) { + // m3u8 指向新连接 + tmp := strings.TrimSpace(string(m3u[i+1])) + if redirectUrl == "" { + redirectUrl = tmp + } + if qn, e := strconv.Atoi(ParseQuery(tmp, "qn=")); e == nil { + if maxqn < qn { + maxqn = qn + redirectUrl = tmp + } + } + err = ErrRedirect + } + } + if t.IsErrRedirect(err) { + return + } + + m4sLink = func(yield func(interface { + IsHeader() bool + M4sLink() string + }) bool) { + for i := 0; i < len(m3u); i++ { + line := m3u[i] + if len(line) == 0 { + continue + } + + var ( + m4sLink string //切片文件名 + isHeader bool + ) + + if line[0] == '#' { + if bytes.HasPrefix(line, extXMap) { + if lastNo != 0 { + continue + } + e := bytes.Index(line[16:], []byte(`"`)) + 16 + m4sLink = string(line[16:e]) + isHeader = true + } else { + continue + } + } else { + m4sLink = string(line) + } + + if !isHeader { + // 只增加新的切片 + if no, _ := strconv.Atoi(m4sLink[:len(m4sLink)-4]); lastNo >= no { + continue + } + } + + if !yield(parseM3u8I{ + header: isHeader, + link: m4sLink, + }) { + break + } + } + } + return +} + +// just faster, use in right way +// +// eg. ParseQuery(`http://1.com/2?workspace=1`, "workspace=") => `1` +func ParseQuery(rawURL, key string) string { + s := 0 + for i := 0; i < len(rawURL); i++ { + if rawURL[i] == '?' { + s = i + 1 + break + } + } + + for i := s; i < len(rawURL); i++ { + for j := 0; i < len(rawURL) && j < len(key); j, i = j+1, i+1 { + if rawURL[i] != key[j] { + break + } else if j == len(key)-1 { + s = i + 1 + i = len(rawURL) + break + } + } + } + + d := s + for ; d < len(rawURL); d++ { + if rawURL[d] == '&' || rawURL[d] == '#' { + break + } + } + + return rawURL[s:d] +} diff --git a/Reply/F/parseM3u8/parseM3u8_test.go b/Reply/F/parseM3u8/parseM3u8_test.go new file mode 100644 index 0000000..89ca77f --- /dev/null +++ b/Reply/F/parseM3u8/parseM3u8_test.go @@ -0,0 +1,30 @@ +package parsem3u8 + +import ( + "iter" + "testing" + + _ "embed" + + comp "github.com/qydysky/part/component2" +) + +//go:embed test.m3u8 +var testM3u8 []byte + +func TestMain(t *testing.T) { + var ParseM3u8 = comp.Get[interface { + Parse(respon []byte, lastNo int) (m4sLink iter.Seq[interface { + IsHeader() bool + M4sLink() string + }], redirectUrl string, err error) + IsErrRedirect(e error) bool + }](`parseM3u8`) + _, url, e := ParseM3u8.Parse(testM3u8, 0) + if !ParseM3u8.IsErrRedirect(e) { + t.Fatal() + } + if url != "https://d1--cn-gotcha209.bilivideo.com/live-bvc/192693/live_194484313_8775758_bluray/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=10000&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha209&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&deploy_env=prod&hot_cdn=909773&origin_bitrate=1272698&source=puv3_master&flvsk=x&suffix=bluray&pp=rtmp&qp=bqor_250&sl=10&p2p_type=1&sk=x&score=42&info_source=cache&vd=bc&src=puv3&order=1" { + t.Fatal() + } +} diff --git a/Reply/F/parseM3u8/test.m3u8 b/Reply/F/parseM3u8/test.m3u8 new file mode 100644 index 0000000..64a9dc0 --- /dev/null +++ b/Reply/F/parseM3u8/test.m3u8 @@ -0,0 +1,26 @@ +#EXTM3U +#EXT-X-CONTENT-STEERING:SERVER-URI="reserved",PATHWAY-ID="https://d1--cn-gotcha209.bilivideo.com",BILI-PATHWAY-PRIORITY="https://d1--cn-gotcha209.bilivideo.com,https://cn-hnzz-cm-01-11.bilivideo.com,https://d1--cn-gotcha204.bilivideo.com,https://d1--cn-gotcha208.bilivideo.com,https://cn-zjhz-cm-01-17.bilivideo.com,https://d1--cn-gotcha204-1.bilivideo.com,https://cn-hnzz-cm-01-09.bilivideo.com,https://d1--cn-gotcha204-4.bilivideo.com",BILI-CTR-MODE=1,BILI-TTL=150 +#EXT-X-STREAM-INF:BANDWIDTH=1187465,RESOLUTION=1280x720,CODECS="avc1.640028,mp4a.40.2",BILI-ORDER=0,BILI-DISPLAY="超清",BILI-QN=250,PATHWAY-ID="https://d1--cn-gotcha209.bilivideo.com" +https://d1--cn-gotcha209.bilivideo.com/live-bvc/833265/live_194484313_8775758_2500/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=250&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha209&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&p2p_type=1&sl=10&qp=bqor_250&source=puv3_master&sk=x&deploy_env=prod&score=37&hot_cdn=909773&info_source=cache&suffix=2500&origin_bitrate=1272698&flvsk=x&pp=rtmp&vd=bc&src=puv3&order=1 +#EXT-X-STREAM-INF:BANDWIDTH=1187465,RESOLUTION=1280x720,CODECS="avc1.640028,mp4a.40.2",BILI-ORDER=0,BILI-DISPLAY="超清",BILI-QN=250,PATHWAY-ID="https://cn-hnzz-cm-01-11.bilivideo.com" +https://cn-hnzz-cm-01-11.bilivideo.com/live-bvc/833265/live_194484313_8775758_2500/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=250&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha01&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&sid=cn-hnzz-cm-01-11&chash=1&bmt=1&sg=lr&trace=65&isp=cm&rg=South&pv=Guangdong&p2p_type=1&sl=10&qp=bqor_250&source=puv3_master&deploy_env=prod&score=37&hot_cdn=909773&info_source=cache&suffix=2500&origin_bitrate=1272698&flvsk=x&sk=x&pp=rtmp&vd=nc&zoneid_l=151371779&sid_l=live_194484313_8775758_2500&src=puv3&order=2 +#EXT-X-STREAM-INF:BANDWIDTH=1187465,RESOLUTION=1280x720,CODECS="avc1.640028,mp4a.40.2",BILI-ORDER=0,BILI-DISPLAY="超清",BILI-QN=250,PATHWAY-ID="https://d1--cn-gotcha204.bilivideo.com" +https://d1--cn-gotcha204.bilivideo.com/live-bvc/833265/live_194484313_8775758_2500/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=250&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha204&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&p2p_type=1&sl=10&qp=bqor_250&source=puv3_master&deploy_env=prod&score=37&hot_cdn=909773&info_source=cache&suffix=2500&origin_bitrate=1272698&flvsk=x&sk=x&pp=rtmp&vd=bc&src=puv3&order=3 +#EXT-X-STREAM-INF:BANDWIDTH=1187465,RESOLUTION=1280x720,CODECS="avc1.640028,mp4a.40.2",BILI-ORDER=0,BILI-DISPLAY="超清",BILI-QN=250,PATHWAY-ID="https://d1--cn-gotcha208.bilivideo.com" +https://d1--cn-gotcha208.bilivideo.com/live-bvc/833265/live_194484313_8775758_2500/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=250&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha208&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&flvsk=x&sk=x&deploy_env=prod&score=37&hot_cdn=909773&info_source=cache&suffix=2500&origin_bitrate=1272698&pp=rtmp&source=puv3_master&p2p_type=1&sl=10&qp=bqor_250&vd=bc&src=puv3&order=4 +#EXT-X-STREAM-INF:BANDWIDTH=1724079,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2",BILI-ORDER=1,BILI-DISPLAY="蓝光",BILI-QN=400,PATHWAY-ID="https://d1--cn-gotcha209.bilivideo.com" +https://d1--cn-gotcha209.bilivideo.com/live-bvc/378106/live_194484313_8775758_4000/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=400&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha209&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&sl=10&qp=bqor_250&flvsk=x&deploy_env=prod&suffix=4000&p2p_type=1&score=57&origin_bitrate=1272698&source=puv3_master&sk=x&info_source=cache&hot_cdn=909773&pp=rtmp&vd=bc&src=puv3&order=1 +#EXT-X-STREAM-INF:BANDWIDTH=1724079,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2",BILI-ORDER=1,BILI-DISPLAY="蓝光",BILI-QN=400,PATHWAY-ID="https://cn-zjhz-cm-01-17.bilivideo.com" +https://cn-zjhz-cm-01-17.bilivideo.com/live-bvc/378106/live_194484313_8775758_4000/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=400&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha01&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&sid=cn-zjhz-cm-01-17&chash=1&bmt=1&sg=lr&trace=65&isp=cm&rg=South&pv=Guangdong&deploy_env=prod&suffix=4000&p2p_type=1&sl=10&qp=bqor_250&flvsk=x&sk=x&info_source=cache&hot_cdn=909773&pp=rtmp&score=57&origin_bitrate=1272698&source=puv3_master&vd=nc&zoneid_l=151371779&sid_l=live_194484313_8775758_4000&src=puv3&order=2 +#EXT-X-STREAM-INF:BANDWIDTH=1724079,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2",BILI-ORDER=1,BILI-DISPLAY="蓝光",BILI-QN=400,PATHWAY-ID="https://d1--cn-gotcha204-1.bilivideo.com" +https://d1--cn-gotcha204-1.bilivideo.com/live-bvc/378106/live_194484313_8775758_4000/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=400&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha204&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&sk=x&info_source=cache&hot_cdn=909773&pp=rtmp&score=57&origin_bitrate=1272698&source=puv3_master&deploy_env=prod&suffix=4000&p2p_type=1&sl=10&qp=bqor_250&flvsk=x&vd=bc&src=puv3&order=3 +#EXT-X-STREAM-INF:BANDWIDTH=1724079,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2",BILI-ORDER=1,BILI-DISPLAY="蓝光",BILI-QN=400,PATHWAY-ID="https://d1--cn-gotcha208.bilivideo.com" +https://d1--cn-gotcha208.bilivideo.com/live-bvc/378106/live_194484313_8775758_4000/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=400&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha208&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&sl=10&qp=bqor_250&flvsk=x&deploy_env=prod&suffix=4000&p2p_type=1&score=57&origin_bitrate=1272698&source=puv3_master&sk=x&info_source=cache&hot_cdn=909773&pp=rtmp&vd=bc&src=puv3&order=4 +#EXT-X-STREAM-INF:BANDWIDTH=2108696,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2",BILI-ORDER=2,BILI-DISPLAY="原画",BILI-QN=10000,PATHWAY-ID="https://d1--cn-gotcha209.bilivideo.com" +https://d1--cn-gotcha209.bilivideo.com/live-bvc/192693/live_194484313_8775758_bluray/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=10000&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha209&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&deploy_env=prod&hot_cdn=909773&origin_bitrate=1272698&source=puv3_master&flvsk=x&suffix=bluray&pp=rtmp&qp=bqor_250&sl=10&p2p_type=1&sk=x&score=42&info_source=cache&vd=bc&src=puv3&order=1 +#EXT-X-STREAM-INF:BANDWIDTH=2108696,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2",BILI-ORDER=2,BILI-DISPLAY="原画",BILI-QN=10000,PATHWAY-ID="https://cn-hnzz-cm-01-09.bilivideo.com" +https://cn-hnzz-cm-01-09.bilivideo.com/live-bvc/192693/live_194484313_8775758_bluray/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=10000&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha01&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&sid=cn-hnzz-cm-01-09&chash=1&bmt=1&sg=lr&trace=65&isp=cm&rg=South&pv=Guangdong&flvsk=x&suffix=bluray&pp=rtmp&qp=bqor_250&deploy_env=prod&hot_cdn=909773&origin_bitrate=1272698&source=puv3_master&info_source=cache&sl=10&p2p_type=1&sk=x&score=42&vd=nc&zoneid_l=151371779&sid_l=live_194484313_8775758_bluray&src=puv3&order=2 +#EXT-X-STREAM-INF:BANDWIDTH=2108696,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2",BILI-ORDER=2,BILI-DISPLAY="原画",BILI-QN=10000,PATHWAY-ID="https://d1--cn-gotcha204-4.bilivideo.com" +https://d1--cn-gotcha204-4.bilivideo.com/live-bvc/192693/live_194484313_8775758_bluray/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=10000&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha204&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&sl=10&p2p_type=1&sk=x&score=42&info_source=cache&pp=rtmp&qp=bqor_250&deploy_env=prod&hot_cdn=909773&origin_bitrate=1272698&source=puv3_master&flvsk=x&suffix=bluray&vd=bc&src=puv3&order=3 +#EXT-X-STREAM-INF:BANDWIDTH=2108696,RESOLUTION=1920x1080,CODECS="avc1.640032,mp4a.40.2",BILI-ORDER=2,BILI-DISPLAY="原画",BILI-QN=10000,PATHWAY-ID="https://d1--cn-gotcha208.bilivideo.com" +https://d1--cn-gotcha208.bilivideo.com/live-bvc/192693/live_194484313_8775758_bluray/index.m3u8?expires=1737129387&len=0&oi=x&pt=web&qn=10000&trid=x&sigparams=cdn,expires,len,oi,pt,qn,trid&cdn=cn-gotcha208&sign=x&site=x&free_type=0&mid=x&sche=ban&bvchls=1&trace=64&isp=cm&rg=South&pv=Guangdong&qp=bqor_250&deploy_env=prod&hot_cdn=909773&origin_bitrate=1272698&source=puv3_master&flvsk=x&suffix=bluray&pp=rtmp&sl=10&p2p_type=1&sk=x&score=42&info_source=cache&vd=bc&src=puv3&order=4 \ No newline at end of file diff --git a/Reply/stream.go b/Reply/stream.go index 40fdcfe..7021206 100644 --- a/Reply/stream.go +++ b/Reply/stream.go @@ -1,11 +1,9 @@ package reply import ( - "bytes" "context" "crypto/md5" _ "embed" - "encoding/base64" "encoding/json" "errors" "fmt" @@ -448,7 +446,9 @@ func (t *M4SStream) fetchParseM3U8(lastM4s *m4s_link_item, fmp4ListUpdateTo floa defer t.reqPool.Put(r) // 请求解析m3u8内容 - for _, v := range t.common.Live { + for i := 0; i < len(t.common.Live); i++ { + v := t.common.Live[i] + // 跳过尚未启用的live地址 if !v.Valid() { continue @@ -477,7 +477,6 @@ func (t *M4SStream) fetchParseM3U8(lastM4s *m4s_link_item, fmp4ListUpdateTo floa } if err := r.Reqf(rval); err != nil { - // 1min后重新启用 v.DisableAuto() t.log.L("W: ", fmt.Sprintf("服务器 %s 发生故障 %s", F.ParseHost(v.Url), pe.ErrorFormat(err, pe.ErrSimplifyFunc))) if t.common.ValidLive() == nil { @@ -499,19 +498,6 @@ func (t *M4SStream) fetchParseM3U8(lastM4s *m4s_link_item, fmp4ListUpdateTo floa } } - // m3u8字节流 - var m3u8_respon = r.Respon - - // base64解码 - if len(m3u8_respon) != 0 && !bytes.Contains(m3u8_respon, []byte("#")) { - var err error - m3u8_respon, err = base64.StdEncoding.DecodeString(string(m3u8_respon)) - if err != nil { - e = err - return - } - } - // 解析m3u8 // var tmp []*m4s_link_item var lastNo int @@ -519,56 +505,33 @@ func (t *M4SStream) fetchParseM3U8(lastM4s *m4s_link_item, fmp4ListUpdateTo floa lastNo, _ = lastM4s.getNo() } - m3u := bytes.Split(m3u8_respon, []byte("\n")) - for i := 0; i < len(m3u); i++ { - line := m3u[i] - if len(line) == 0 { - continue - } - - var ( - m4s_link string //切片文件名 - isHeader bool - ) - - if line[0] == '#' { - if strings.HasPrefix(string(line), "#EXT-X-MAP") { - if lastM4s != nil { - continue - } - e := bytes.Index(line[16:], []byte(`"`)) + 16 - m4s_link = string(line[16:e]) - isHeader = true - } else if strings.HasPrefix(string(line), "#EXT-X-STREAM-INF") { - // m3u8 指向新连接 - i += 1 - line = m3u[i] - newUrl := strings.TrimSpace(string(line)) - t.log.L(`I: `, `指向新连接`, v.Host(), "=>", F.ParseHost(newUrl)) - v.SetUrl(newUrl) - continue - } else { - continue - } + if rg, redirectUrl, err := replyFunc.ParseM3u8.Parse(r.Respon, lastNo); err != nil { + if replyFunc.ParseM3u8.IsErrRedirect(err) { + // 指向新连接 + t.log.L(`I: `, `指向新连接`, v.Host(), "=>", F.ParseHost(redirectUrl)) + v.SetUrl(redirectUrl) + i -= 1 } else { - m4s_link = string(line) - } - - if !isHeader { - // 只增加新的切片 - if no, _ := strconv.Atoi(m4s_link[:len(m4s_link)-4]); lastNo >= no { - continue + // 1min后重新启用 + t.log.L("W: ", fmt.Sprintf("服务器 %s 发生故障 %v", F.ParseHost(v.Url), err)) + v.DisableAuto() + if t.common.ValidLive() == nil { + e = errors.New("全部切片服务器发生故障") + break } } - - //将切片添加到返回切片数组 - p := t.getM4s() - p.SerUuid = v.Uuid - p.Url = F.ResolveReferenceLast(v.Url, m4s_link+"?trid="+F.ParseQuery(v.Url, "trid=")) - p.Base = m4s_link - p.isHeader = isHeader - p.createdTime = time.Now() - m4s_links = append(m4s_links, p) + continue + } else { + for m4sLinkI := range rg { + //将切片添加到返回切片数组 + p := t.getM4s() + p.SerUuid = v.Uuid + p.Url = F.ResolveReferenceLast(v.Url, m4sLinkI.M4sLink()+"?trid="+F.ParseQuery(v.Url, "trid=")) + p.Base = m4sLinkI.M4sLink() + p.isHeader = m4sLinkI.IsHeader() + p.createdTime = time.Now() + m4s_links = append(m4s_links, p) + } } if len(m4s_links) == 0 {