]> 127.0.0.1 Git - bili_danmu/.git/commitdiff
MP4自动调整音频时间戳 v0.5.10
authorqydysky <32743305+qydysky@users.noreply.github.com>
Mon, 31 Oct 2022 18:57:12 +0000 (02:57 +0800)
committerqydysky <32743305+qydysky@users.noreply.github.com>
Mon, 31 Oct 2022 18:57:12 +0000 (02:57 +0800)
F/B_I.go
F/B_I_test.go [new file with mode: 0644]
Reply/fmp4Decode.go
Reply/stream.go

index 11c02ef8e0f1a6d9f6fb73dab1e571fca88bf6c7..8c93fa2d3133a2b6540b66c14e70fc7974592725 100644 (file)
--- a/F/B_I.go
+++ b/F/B_I.go
@@ -9,9 +9,19 @@ import (
 
 /*
 整数 字节转换区
+64 8字节
 32 4字节
 16 2字节
 */
+func Itob64(num int64) []byte {
+       var buffer bytes.Buffer
+       err := binary.Write(&buffer, binary.BigEndian, num)
+       if err != nil {
+               p.Logf().E(err)
+       }
+       return buffer.Bytes()
+}
+
 func Itob32(num int32) []byte {
        var buffer bytes.Buffer
        err := binary.Write(&buffer, binary.BigEndian, num)
@@ -30,6 +40,15 @@ func Itob16(num int16) []byte {
        return buffer.Bytes()
 }
 
+func btoi64(b []byte) int64 {
+       var buffer int64
+       err := binary.Read(bytes.NewReader(b), binary.BigEndian, &buffer)
+       if err != nil {
+               p.Logf().E(err)
+       }
+       return buffer
+}
+
 func btoi32(b []byte) int32 {
        var buffer int32
        err := binary.Read(bytes.NewReader(b), binary.BigEndian, &buffer)
@@ -48,10 +67,23 @@ func btoi16(b []byte) int16 {
        return buffer
 }
 
+func Btoi64(b []byte, offset int) int64 {
+       for len(b) < 8 {
+               b = append([]byte{0x00}, b...)
+       }
+       return btoi64(b[offset : offset+8])
+}
+
 func Btoi32(b []byte, offset int) int32 {
+       for len(b) < 4 {
+               b = append([]byte{0x00}, b...)
+       }
        return btoi32(b[offset : offset+4])
 }
 
 func Btoi16(b []byte, offset int) int16 {
+       for len(b) < 2 {
+               b = append([]byte{0x00}, b...)
+       }
        return btoi16(b[offset : offset+2])
 }
diff --git a/F/B_I_test.go b/F/B_I_test.go
new file mode 100644 (file)
index 0000000..bd1bc9c
--- /dev/null
@@ -0,0 +1,11 @@
+package F
+
+import "testing"
+
+func TestBtoi32(t *testing.T) {
+       t.Log(Btoi64([]byte{0xd6, 0xfd, 0x62, 0x50}, 0))
+}
+
+func TestItob32(t *testing.T) {
+       t.Log(Itob64(1131984000))
+}
index ef7ed5a12a8ae10209313790b236654e2c5c9d64..919488a1a86690c972eda5d09b8f0eb342d29493 100644 (file)
@@ -7,58 +7,176 @@ import (
        F "github.com/qydysky/bili_danmu/F"
 )
 
-type fmp4KeyFrame struct {
-       videoTime int
-       audioTime int
-       data      []byte
+type trak struct {
+       timescale   int
+       trackID     int
+       handlerType byte
 }
 
-func Seach_stream_fmp4(buf []byte) (keyframes []fmp4KeyFrame, last_avilable_offset int, err error) {
+type Fmp4Decoder struct {
+       traks map[int]trak
+}
+
+func (t *Fmp4Decoder) Init_fmp4(buf []byte) error {
+       var cu int
+       for cu < len(buf) {
+               //moov
+               moovI := bytes.Index(buf[cu:], []byte("moov"))
+               if moovI == -1 {
+                       break
+               }
+               moovI = cu + moovI - 4
+               cu = moovI
+               moovE := moovI + int(F.Btoi32(buf, moovI))
+               if moovE > len(buf) {
+                       return errors.New("moov包破损")
+               }
+
+               for cu < moovE {
+                       //trak
+                       trakI := bytes.Index(buf[cu:], []byte("trak"))
+                       if trakI == -1 {
+                               break
+                       }
+                       trakI = cu + trakI - 4
+                       cu = trakI
+                       trakE := trakI + int(F.Btoi32(buf, trakI))
+                       if trakE > moovE {
+                               return errors.New("trak包破损")
+                       }
+
+                       //tkhd
+                       tkhdI := bytes.Index(buf[cu:], []byte("tkhd"))
+                       if tkhdI == -1 {
+                               return errors.New("未找到tkhd包")
+                       }
+                       tkhdI = cu + tkhdI - 4
+                       cu = tkhdI
+                       tkhdE := tkhdI + int(F.Btoi32(buf, tkhdI))
+                       if tkhdE > trakE {
+                               return errors.New("tkhd包破损")
+                       }
+
+                       //mdia
+                       mdiaI := bytes.Index(buf[cu:], []byte("mdia"))
+                       if mdiaI == -1 {
+                               return errors.New("未找到mdia包")
+                       }
+                       mdiaI = cu + mdiaI - 4
+                       cu = mdiaI
+                       mdiaE := mdiaI + int(F.Btoi32(buf, mdiaI))
+                       if mdiaE > trakE {
+                               return errors.New("mdia包破损")
+                       }
+
+                       //mdhd
+                       mdhdI := bytes.Index(buf[cu:], []byte("mdhd"))
+                       if mdhdI == -1 {
+                               return errors.New("未找到mdhd包")
+                       }
+                       mdhdI = cu + mdhdI - 4
+                       cu = mdhdI
+                       mdhdE := mdhdI + int(F.Btoi32(buf, mdhdI))
+                       if mdhdE > mdiaE {
+                               return errors.New("mdhd包破损")
+                       }
+
+                       //hdlr
+                       hdlrI := bytes.Index(buf[cu:], []byte("hdlr"))
+                       if hdlrI == -1 {
+                               return errors.New("未找到hdlr包")
+                       }
+                       hdlrI = cu + hdlrI - 4
+                       cu = hdlrI
+                       hdlrE := hdlrI + int(F.Btoi32(buf, hdlrI))
+                       if hdlrE > mdiaE {
+                               return errors.New("hdlr包破损")
+                       }
+
+                       tackId := int(F.Btoi32(buf, tkhdI+20))
+                       if t.traks == nil {
+                               t.traks = make(map[int]trak)
+                       }
+                       t.traks[tackId] = trak{
+                               trackID:     tackId,
+                               timescale:   int(F.Btoi32(buf, mdhdI+20)),
+                               handlerType: buf[hdlrI+16],
+                       }
+               }
+       }
+       if len(t.traks) == 0 {
+               return errors.New("未找到trak包")
+       }
+       return nil
+}
+
+func (t *Fmp4Decoder) Seach_stream_fmp4(buf []byte) (keyframes [][]byte, last_avilable_offset int, err error) {
+       if len(t.traks) == 0 {
+               err = errors.New("未初始化traks")
+               return
+       }
+
        var (
                cu       int
-               keyframe fmp4KeyFrame
+               keyframe []byte
        )
 
        for cu < len(buf) {
                //moof
-               moofI := cu + bytes.Index(buf[cu:], []byte("moof")) - 4
+               moofI := bytes.Index(buf[cu:], []byte("moof"))
                if moofI == -1 {
-                       err = errors.New("未找到moof包")
                        break
                }
+               moofI = cu + moofI - 4
+               cu = moofI
                moofE := moofI + int(F.Btoi32(buf, moofI))
                if moofE > len(buf) {
                        break
                }
-               cu = moofI
 
                var (
-                       iskeyFrame bool
-                       videoTime  int
-                       audioTime  int
+                       iskeyFrame     bool
+                       videoTime      float64
+                       audioTime      float64
+                       audioTimeIndex int
+                       audioTimeSize  int
+                       audioTimeScale int
                )
 
-               for trafCount := 0; trafCount < 2 && cu < moofE; trafCount += 1 {
-
+               for cu < moofE {
                        //traf
-                       trafI := cu + bytes.Index(buf[cu:], []byte("traf")) - 4
+                       trafI := bytes.Index(buf[cu:], []byte("traf"))
                        if trafI == -1 {
-                               err = errors.New("未找到traf包")
                                break
                        }
+                       trafI = cu + trafI - 4
                        cu = trafI
                        trafE := trafI + int(F.Btoi32(buf, trafI))
                        if trafE > moofE {
-                               err = errors.New("traf包破损")
+                               break
+                       }
+
+                       //tfhd
+                       tfhdI := bytes.Index(buf[cu:], []byte("tfhd"))
+                       if tfhdI == -1 {
+                               err = errors.New("未找到tfhd包")
+                               break
+                       }
+                       tfhdI = cu + tfhdI - 4
+                       cu = tfhdI
+                       tfhdE := tfhdI + int(F.Btoi32(buf, tfhdI))
+                       if tfhdE > trafE {
+                               err = errors.New("tfhd包破损")
                                break
                        }
 
                        //tfdt
-                       tfdtI := cu + bytes.Index(buf[cu:], []byte("tfdt")) - 4
+                       tfdtI := bytes.Index(buf[cu:], []byte("tfdt"))
                        if tfdtI == -1 {
                                err = errors.New("未找到tfdt包")
                                break
                        }
+                       tfdtI = cu + tfdtI - 4
                        cu = tfdtI
                        tfdtE := tfdtI + int(F.Btoi32(buf, tfdtI))
                        if tfdtE > trafE {
@@ -67,11 +185,12 @@ func Seach_stream_fmp4(buf []byte) (keyframes []fmp4KeyFrame, last_avilable_offs
                        }
 
                        //trun
-                       trunI := cu + bytes.Index(buf[cu:], []byte("trun")) - 4
+                       trunI := bytes.Index(buf[cu:], []byte("trun"))
                        if trunI == -1 {
                                err = errors.New("未找到trun包")
                                break
                        }
+                       trunI = cu + trunI - 4
                        cu = trunI
                        trunE := trunI + int(F.Btoi32(buf, trunI))
                        if trunE > trafE {
@@ -79,11 +198,37 @@ func Seach_stream_fmp4(buf []byte) (keyframes []fmp4KeyFrame, last_avilable_offs
                                break
                        }
 
-                       timeStamp := int(F.Btoi32(buf, tfdtI+16))
-                       if trafCount == 0 {
-                               videoTime = timeStamp
-                       } else if trafCount == 1 {
-                               audioTime = timeStamp
+                       var (
+                               timeStamp      int
+                               timeStampIndex int
+                               timeSize       int
+                       )
+                       switch buf[tfdtI+8] {
+                       case 0:
+                               timeSize = 4
+                               timeStampIndex = tfdtI + 16
+                               timeStamp = int(F.Btoi32(buf, tfdtI+16))
+                       case 1:
+                               timeSize = 8
+                               timeStampIndex = tfdtI + 12
+                               timeStamp = int(F.Btoi64(buf, tfdtI+12))
+                       }
+
+                       track, ok := t.traks[int(F.Btoi32(buf, tfhdI+12))]
+                       if !ok {
+                               err = errors.New("找不到trak")
+                               // log.Default().Println(`cant find trak`, int(F.Btoi32(buf, tfhdI+12)))
+                               continue
+                       }
+
+                       switch track.handlerType {
+                       case 'v':
+                               videoTime = float64(timeStamp) / float64(track.timescale)
+                       case 's':
+                               audioTimeIndex = timeStampIndex
+                               audioTimeSize = timeSize
+                               audioTimeScale = track.timescale
+                               audioTime = float64(timeStamp) / float64(track.timescale)
                        }
 
                        if !iskeyFrame && buf[trunI+20] == byte(0x02) {
@@ -95,23 +240,40 @@ func Seach_stream_fmp4(buf []byte) (keyframes []fmp4KeyFrame, last_avilable_offs
                        break
                }
 
+               //change audio timeStamp
+               if audioTime != videoTime {
+                       // err = errors.New("重新设置音频时间戳")
+                       switch audioTimeSize {
+                       case 4:
+                               // log.Default().Println("set audio to:", int32(videoTime*float64(audioTimeScale)))
+                               date := F.Itob32(int32(videoTime * float64(audioTimeScale)))
+                               for i := 0; i < audioTimeSize; i += 1 {
+                                       buf[audioTimeIndex+i] = date[i]
+                               }
+                       case 8:
+                               // log.Default().Println("set audio to:", int64(videoTime*float64(audioTimeScale)))
+                               date := F.Itob64(int64(videoTime * float64(audioTimeScale)))
+                               for i := 0; i < audioTimeSize; i += 1 {
+                                       buf[audioTimeIndex+i] = date[i]
+                               }
+                       }
+               }
+
                if iskeyFrame {
                        last_avilable_offset = moofI - 1
-                       if len(keyframe.data) != 0 {
+                       if len(keyframe) != 0 {
                                keyframes = append(keyframes, keyframe)
                        }
-                       keyframe = fmp4KeyFrame{
-                               videoTime: videoTime,
-                               audioTime: audioTime,
-                       }
+                       keyframe = []byte{}
                }
 
                //mdat
-               mdatI := cu + bytes.Index(buf[cu:], []byte("mdat")) - 4
+               mdatI := bytes.Index(buf[cu:], []byte("mdat"))
                if moofI == -1 {
                        err = errors.New("未找到mdat包")
                        break
                }
+               mdatI = cu + mdatI - 4
                cu = mdatI
                mdatE := mdatI + int(F.Btoi32(buf, mdatI))
                if mdatE > len(buf) {
@@ -119,8 +281,7 @@ func Seach_stream_fmp4(buf []byte) (keyframes []fmp4KeyFrame, last_avilable_offs
                        break
                }
 
-               keyframe.data = append(keyframe.data, buf[moofI:mdatE]...)
-               cu = mdatE
+               keyframe = append(keyframe, buf[moofI:mdatE]...)
        }
 
        return
index 9385789e76739c155423dc35e5874190d79b7d2b..4ecfc4a5e44739c1b6f5f614b27d4619dbcdbf75 100644 (file)
@@ -639,13 +639,8 @@ func (t *M4SStream) saveStreamM4s() (e error) {
 
        //
        var (
-               buf              []byte
-               lastVideoTime    int
-               lastAudioTime    int
-               diffVideoTime    int
-               diffAudioTime    int
-               diffSumVideoTime int
-               diffSumAudioTime int
+               buf         []byte
+               fmp4Decoder = &Fmp4Decoder{}
        )
 
        // 下载循环
@@ -729,6 +724,13 @@ func (t *M4SStream) saveStreamM4s() (e error) {
                                        buf = append(buf, v.data...)
 
                                        if strings.Contains(v.Base, `h`) {
+                                               if e := fmp4Decoder.Init_fmp4(v.data); e != nil {
+                                                       t.log.L(`E: `, e)
+                                               } else {
+                                                       for _, trak := range fmp4Decoder.traks {
+                                                               t.log.L(`T: `, "找到trak:", string(trak.handlerType), trak.trackID, trak.timescale)
+                                                       }
+                                               }
                                                t.first_buf = v.data
                                                if t.config.save_as_mp4 {
                                                        out.Write(v.data)
@@ -736,41 +738,16 @@ func (t *M4SStream) saveStreamM4s() (e error) {
                                                continue
                                        }
 
-                                       fmp4KeyFrames, last_avilable_offset, e := Seach_stream_fmp4(buf)
+                                       fmp4KeyFrames, last_avilable_offset, e := fmp4Decoder.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: `, `时间戳失去同步`)
-                                                       }
+                                               t.bootBufPush(fmp4KeyFrame)
+                                               t.Stream_msg.Push_tag(`data`, fmp4KeyFrame)
+                                               if t.config.save_as_mp4 {
+                                                       out.Write(fmp4KeyFrame)
                                                }
                                        }