mp3mp4_duration.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package common
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "mime/multipart"
  6. )
  7. // GetMediaDuration 得到媒体文件时长
  8. func GetMediaDuration(reader multipart.File, contentType string) (int, error) {
  9. var duration int
  10. var err error
  11. if contentType == "video/mp4" {
  12. duration, err = GetMP4Duration(reader)
  13. }
  14. if contentType == "audio/mpeg" {
  15. duration, err = GetMP3PlayDuration(reader)
  16. }
  17. if err != nil {
  18. return 0, err
  19. }
  20. return duration * 1000, err
  21. }
  22. // GetMP4Duration 获取视频时长,以秒计
  23. func GetMP4Duration(reader multipart.File) (lengthOfTime int, err error) {
  24. var info = make([]byte, 0x10)
  25. var boxHeader BoxHeader
  26. var offset int64 = 0
  27. // 获取moov结构偏移
  28. for {
  29. _, err = reader.ReadAt(info, offset)
  30. if err != nil {
  31. return
  32. }
  33. boxHeader = getHeaderBoxInfo(info)
  34. fourccType := getFourccType(boxHeader)
  35. if fourccType == "moov" {
  36. break
  37. }
  38. // 有一部分mp4 mdat尺寸过大需要特殊处理
  39. if fourccType == "mdat" {
  40. if boxHeader.Size == 1 {
  41. offset += int64(boxHeader.Size64)
  42. continue
  43. }
  44. }
  45. offset += int64(boxHeader.Size)
  46. }
  47. // 获取moov结构开头一部分
  48. moovStartBytes := make([]byte, 0x100)
  49. _, err = reader.ReadAt(moovStartBytes, offset)
  50. if err != nil {
  51. return
  52. }
  53. // 定义timeScale与Duration偏移
  54. timeScaleOffset := 0x1C
  55. durationOffest := 0x20
  56. timeScale := binary.BigEndian.Uint32(moovStartBytes[timeScaleOffset : timeScaleOffset+4])
  57. Duration := binary.BigEndian.Uint32(moovStartBytes[durationOffest : durationOffest+4])
  58. lengthOfTime = int(Duration / timeScale)
  59. return
  60. }
  61. // GetMP3PlayDuration 获取mp3时长,以秒计
  62. func GetMP3PlayDuration(reader multipart.File) (seconds int, err error) {
  63. return 0, nil
  64. //buf := bytes.NewBuffer(nil)
  65. //if _, err := io.Copy(buf, reader); err != nil {
  66. // return 0, err
  67. //}
  68. //mp3Data := buf.Bytes()
  69. //dec, _, err := minimp3.DecodeFull(mp3Data)
  70. //if err != nil {
  71. // return 0, err
  72. //}
  73. //// 音乐时长 = (文件大小(byte) - 128(ID3信息)) * 8(to bit) / (码率(kbps b:bit) * 1000)(kilo bit to bit)
  74. //seconds = (len(mp3Data) - 128) * 8 / (dec.Kbps * 1000)
  75. //return seconds, nil
  76. }
  77. // BoxHeader 信息头
  78. type BoxHeader struct {
  79. Size uint32
  80. FourccType [4]byte
  81. Size64 uint64
  82. }
  83. func getHeaderBoxInfo(data []byte) (boxHeader BoxHeader) {
  84. buf := bytes.NewBuffer(data)
  85. binary.Read(buf, binary.BigEndian, &boxHeader)
  86. return
  87. }
  88. // getFourccType 获取信息头类型
  89. func getFourccType(boxHeader BoxHeader) (fourccType string) {
  90. fourccType = string(boxHeader.FourccType[:])
  91. return
  92. }