]> 127.0.0.1 Git - bili_danmu/.git/commitdiff
fmp4丢弃时间戳异常关键帧
authorqydysky <32743305+qydysky@users.noreply.github.com>
Sun, 30 Oct 2022 21:50:22 +0000 (05:50 +0800)
committerqydysky <32743305+qydysky@users.noreply.github.com>
Sun, 30 Oct 2022 21:50:22 +0000 (05:50 +0800)
F/B_I.go
Reply/fmp4Decode.go [new file with mode: 0644]
Reply/stream.go
VERSION
bili_danmu.go

index 465010f9d1e0213cd6c1661b8dff0e5edf19a2d5..11c02ef8e0f1a6d9f6fb73dab1e571fca88bf6c7 100644 (file)
--- a/F/B_I.go
+++ b/F/B_I.go
@@ -6,43 +6,52 @@ import (
 
        p "github.com/qydysky/part"
 )
+
 /*
-       整数 字节转换区
-       32 4字节
-       16 2字节
+整数 字节转换区
+32 4字节
+16 2字节
 */
 func Itob32(num int32) []byte {
        var buffer bytes.Buffer
        err := binary.Write(&buffer, binary.BigEndian, num)
-       if err != nil {p.Logf().E(err)}
+       if err != nil {
+               p.Logf().E(err)
+       }
        return buffer.Bytes()
 }
 
 func Itob16(num int16) []byte {
        var buffer bytes.Buffer
        err := binary.Write(&buffer, binary.BigEndian, num)
-       if err != nil {p.Logf().E(err)}
+       if err != nil {
+               p.Logf().E(err)
+       }
        return buffer.Bytes()
 }
 
 func btoi32(b []byte) int32 {
        var buffer int32
        err := binary.Read(bytes.NewReader(b), binary.BigEndian, &buffer)
-       if err != nil {p.Logf().E(err)}
+       if err != nil {
+               p.Logf().E(err)
+       }
        return buffer
 }
 
 func btoi16(b []byte) int16 {
        var buffer int16
        err := binary.Read(bytes.NewReader(b), binary.BigEndian, &buffer)
-       if err != nil {p.Logf().E(err)}
+       if err != nil {
+               p.Logf().E(err)
+       }
        return buffer
 }
 
 func Btoi32(b []byte, offset int) int32 {
-       return btoi32(b[offset:offset+4])
+       return btoi32(b[offset : offset+4])
 }
 
 func Btoi16(b []byte, offset int) int16 {
-       return btoi16(b[offset:offset+2])
-}
\ No newline at end of file
+       return btoi16(b[offset : offset+2])
+}
diff --git a/Reply/fmp4Decode.go b/Reply/fmp4Decode.go
new file mode 100644 (file)
index 0000000..ef7ed5a
--- /dev/null
@@ -0,0 +1,127 @@
+package reply
+
+import (
+       "bytes"
+       "errors"
+
+       F "github.com/qydysky/bili_danmu/F"
+)
+
+type fmp4KeyFrame struct {
+       videoTime int
+       audioTime int
+       data      []byte
+}
+
+func Seach_stream_fmp4(buf []byte) (keyframes []fmp4KeyFrame, last_avilable_offset int, err error) {
+       var (
+               cu       int
+               keyframe fmp4KeyFrame
+       )
+
+       for cu < len(buf) {
+               //moof
+               moofI := cu + bytes.Index(buf[cu:], []byte("moof")) - 4
+               if moofI == -1 {
+                       err = errors.New("未找到moof包")
+                       break
+               }
+               moofE := moofI + int(F.Btoi32(buf, moofI))
+               if moofE > len(buf) {
+                       break
+               }
+               cu = moofI
+
+               var (
+                       iskeyFrame bool
+                       videoTime  int
+                       audioTime  int
+               )
+
+               for trafCount := 0; trafCount < 2 && cu < moofE; trafCount += 1 {
+
+                       //traf
+                       trafI := cu + bytes.Index(buf[cu:], []byte("traf")) - 4
+                       if trafI == -1 {
+                               err = errors.New("未找到traf包")
+                               break
+                       }
+                       cu = trafI
+                       trafE := trafI + int(F.Btoi32(buf, trafI))
+                       if trafE > moofE {
+                               err = errors.New("traf包破损")
+                               break
+                       }
+
+                       //tfdt
+                       tfdtI := cu + bytes.Index(buf[cu:], []byte("tfdt")) - 4
+                       if tfdtI == -1 {
+                               err = errors.New("未找到tfdt包")
+                               break
+                       }
+                       cu = tfdtI
+                       tfdtE := tfdtI + int(F.Btoi32(buf, tfdtI))
+                       if tfdtE > trafE {
+                               err = errors.New("tfdt包破损")
+                               break
+                       }
+
+                       //trun
+                       trunI := cu + bytes.Index(buf[cu:], []byte("trun")) - 4
+                       if trunI == -1 {
+                               err = errors.New("未找到trun包")
+                               break
+                       }
+                       cu = trunI
+                       trunE := trunI + int(F.Btoi32(buf, trunI))
+                       if trunE > trafE {
+                               err = errors.New("trun包破损")
+                               break
+                       }
+
+                       timeStamp := int(F.Btoi32(buf, tfdtI+16))
+                       if trafCount == 0 {
+                               videoTime = timeStamp
+                       } else if trafCount == 1 {
+                               audioTime = timeStamp
+                       }
+
+                       if !iskeyFrame && buf[trunI+20] == byte(0x02) {
+                               iskeyFrame = true
+                       }
+               }
+
+               if err != nil {
+                       break
+               }
+
+               if iskeyFrame {
+                       last_avilable_offset = moofI - 1
+                       if len(keyframe.data) != 0 {
+                               keyframes = append(keyframes, keyframe)
+                       }
+                       keyframe = fmp4KeyFrame{
+                               videoTime: videoTime,
+                               audioTime: audioTime,
+                       }
+               }
+
+               //mdat
+               mdatI := cu + bytes.Index(buf[cu:], []byte("mdat")) - 4
+               if moofI == -1 {
+                       err = errors.New("未找到mdat包")
+                       break
+               }
+               cu = mdatI
+               mdatE := mdatI + int(F.Btoi32(buf, mdatI))
+               if mdatE > len(buf) {
+                       err = errors.New("mdat包破损")
+                       break
+               }
+
+               keyframe.data = append(keyframe.data, buf[moofI:mdatE]...)
+               cu = mdatE
+       }
+
+       return
+}
index d3303e2e479aa6a8abc9300b0f95c38c572cba6a..9385789e76739c155423dc35e5874190d79b7d2b 100644 (file)
@@ -637,6 +637,17 @@ func (t *M4SStream) saveStreamM4s() (e error) {
                defer out.Close()
        }
 
+       //
+       var (
+               buf              []byte
+               lastVideoTime    int
+               lastAudioTime    int
+               diffVideoTime    int
+               diffAudioTime    int
+               diffSumVideoTime int
+               diffSumAudioTime int
+       )
+
        // 下载循环
        for download_seq := []*m4s_link_item{}; ; {
 
@@ -713,16 +724,58 @@ func (t *M4SStream) saveStreamM4s() (e error) {
                // 传递已下载切片
                {
                        for _, v := range download_seq {
-                               if strings.Contains(v.Base, `h`) {
-                                       t.first_buf = v.data
-                               }
-
                                if v.status == 2 {
                                        download_seq = download_seq[1:]
-                                       t.bootBufPush(v.data)
-                                       t.Stream_msg.Push_tag(`data`, v.data)
-                                       if t.config.save_as_mp4 {
-                                               out.Write(v.data)
+                                       buf = append(buf, v.data...)
+
+                                       if strings.Contains(v.Base, `h`) {
+                                               t.first_buf = v.data
+                                               if t.config.save_as_mp4 {
+                                                       out.Write(v.data)
+                                               }
+                                               continue
+                                       }
+
+                                       fmp4KeyFrames, last_avilable_offset, e := Seach_stream_fmp4(buf)
+                                       if e != nil {
+                                               t.log.L(`E: `, e)
+                                       }
+
+                                       for _, fmp4KeyFrame := range fmp4KeyFrames {
+                                               { // 视频时间戳
+                                                       if lastVideoTime != 0 {
+                                                               if diffVideoTime != 0 {
+                                                                       diffSumVideoTime = fmp4KeyFrame.videoTime - lastVideoTime - diffVideoTime
+                                                               }
+                                                               diffVideoTime = fmp4KeyFrame.videoTime - lastVideoTime
+                                                       }
+                                                       lastVideoTime = fmp4KeyFrame.videoTime
+                                               }
+                                               { // 音频时间戳
+                                                       if lastAudioTime != 0 {
+                                                               if diffAudioTime != 0 {
+                                                                       diffSumAudioTime = fmp4KeyFrame.audioTime - lastAudioTime - diffAudioTime
+                                                               }
+                                                               diffAudioTime = fmp4KeyFrame.audioTime - lastAudioTime
+                                                       }
+                                                       lastAudioTime = fmp4KeyFrame.audioTime
+                                               }
+
+                                               if diffAudioTime != 0 && diffVideoTime != 0 {
+                                                       if math.Abs(float64(diffSumVideoTime)) < 5000 && math.Abs(float64(diffSumAudioTime)) < 5000 {
+                                                               t.bootBufPush(fmp4KeyFrame.data)
+                                                               t.Stream_msg.Push_tag(`data`, fmp4KeyFrame.data)
+                                                               if t.config.save_as_mp4 {
+                                                                       out.Write(fmp4KeyFrame.data)
+                                                               }
+                                                       } else {
+                                                               t.log.L(`W: `, `时间戳失去同步`)
+                                                       }
+                                               }
+                                       }
+
+                                       if last_avilable_offset > 0 {
+                                               buf = buf[last_avilable_offset:]
                                        }
                                } else {
                                        break
diff --git a/VERSION b/VERSION
index 6e48d84cd5ee3a38e7533ebbf5a6d96cde011a3e..a51a1be50888f2060bad9b1136cf4c3877a2b446 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-20210515230141
+20221031054700
\ No newline at end of file
index f7515a203b8b0e59a212d1186fd5dfc88e70bac0..e4176549bdcb1da2f9945f1be4bd2a0c0bdde442 100644 (file)
@@ -1,6 +1,7 @@
 package bili_danmu
 
 import (
+       _ "embed"
        "flag"
        "fmt"
        "net/url"
@@ -21,6 +22,9 @@ import (
        ws "github.com/qydysky/part/websocket"
 )
 
+//go:embed VERSION
+var version string
+
 func init() {
        go func() { //日期变化
                var old = time.Now().Hour()
@@ -41,6 +45,8 @@ func Start(roomid ...int) {
        var stop = sys.Sys().PreventSleep()
        defer stop.Done()
 
+       danmulog.L(`I: `, "version: ", version)
+
        //ctrl+c退出
        interrupt := make(chan os.Signal, 2)
        go func() {