فهرست منبع

支持视频格式扩展

kobe6258 1 روز پیش
والد
کامیت
984fd7b810
1فایلهای تغییر یافته به همراه125 افزوده شده و 92 حذف شده
  1. 125 92
      controllers/video.go

+ 125 - 92
controllers/video.go

@@ -1,7 +1,6 @@
 package controllers
 
 import (
-	"bytes"
 	"encoding/binary"
 	"encoding/json"
 	"eta/eta_mini_crm_ht/models"
@@ -84,12 +83,7 @@ func (this *VideoController) UploadVideo() {
 	duration, err := GetMP4Duration(f)
 	if err != nil {
 		br.Msg = "视频上传失败"
-		br.ErrMsg = "获取MP4时长失败,Err:" + err.Error()
-		return
-	}
-	if err != nil {
-		br.Msg = "音频上传失败"
-		br.ErrMsg = "解析音频时常失败,Err:" + err.Error()
+		br.ErrMsg = "获取视频时长失败,Err:" + err.Error()
 		return
 	}
 
@@ -108,7 +102,7 @@ func (this *VideoController) UploadVideo() {
 		br.ErrMsg = "初始化OSS服务失败"
 		return
 	}
-	mp3Url, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
+	videoUrl, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
 	if err != nil {
 		br.Msg = "视频上传失败"
 		br.ErrMsg = "视频上传失败,Err:" + err.Error()
@@ -116,7 +110,7 @@ func (this *VideoController) UploadVideo() {
 	}
 	base := path.Base(h.Filename)
 	resp := new(response.MediaUploadResp)
-	resp.Url = mp3Url
+	resp.Url = videoUrl
 	resp.FileName = base
 	resp.DurationMillisecond = duration * 1000
 	br.Data = resp
@@ -408,77 +402,6 @@ func (this *VideoController) VideoList() {
 	br.Msg = "获取成功"
 }
 
-type BoxHeader struct {
-	Size       uint32
-	FourccType [4]byte
-	Size64     uint64
-}
-
-// GetMP4Duration 获取视频时长,以秒计
-func GetMP4Duration(reader io.ReaderAt) (lengthOfTime int, err error) {
-	var info = make([]byte, 0x10)
-	var boxHeader BoxHeader
-	var offset int64 = 0
-	// 获取moov结构偏移
-	for {
-		_, err = reader.ReadAt(info, offset)
-		if err == io.EOF {
-			fmt.Println("Reached EOF without finding moov box.")
-			return 0, fmt.Errorf("moov box not found")
-		}
-		if err != nil {
-			return 0, fmt.Errorf("error reading at offset %d: %w", offset, err)
-		}
-
-		boxHeader = getHeaderBoxInfo(info)
-		fourccType := getFourccType(boxHeader)
-
-		if fourccType == "moov" {
-			fmt.Println("Found moov box at offset", offset)
-			break
-		}
-
-		nextOffset := int64(boxHeader.Size)
-		if fourccType == "mdat" && boxHeader.Size == 1 {
-			nextOffset = int64(boxHeader.Size64)
-		}
-		if nextOffset == 0 {
-			return 0, fmt.Errorf("box size is zero, which is invalid and likely means a parsing error")
-		}
-		offset += nextOffset
-	}
-
-	// 获取moov结构开头一部分
-	moovStartBytes := make([]byte, 0x100)
-	_, err = reader.ReadAt(moovStartBytes, offset)
-	if err != nil {
-		return 0, fmt.Errorf("error reading moov box at offset %d: %w", offset, err)
-	}
-	// 定义timeScale与Duration偏移
-	timeScaleOffset := 0x1C
-	durationOffset := 0x20
-	timeScale := binary.BigEndian.Uint32(moovStartBytes[timeScaleOffset : timeScaleOffset+4])
-	duration := binary.BigEndian.Uint32(moovStartBytes[durationOffset : durationOffset+4])
-
-	fmt.Printf("timeScale: %d, duration: %d\n", timeScale, duration)
-	if timeScale == 0 {
-		return 0, fmt.Errorf("timeScale is zero, division by zero is not possible")
-	}
-
-	lengthOfTime = int(duration / timeScale)
-	return
-}
-
-// getHeaderBoxInfo 获取头信息
-func getHeaderBoxInfo(data []byte) (boxHeader BoxHeader) {
-	buf := bytes.NewBuffer(data)
-	binary.Read(buf, binary.BigEndian, &boxHeader)
-	if boxHeader.Size == 1 { // Large Size
-		binary.Read(buf, binary.BigEndian, &boxHeader.Size64)
-	}
-	return
-}
-
 // UploadFile @Title 上传图片
 // @Description 上传视频
 // @Param   File   query   file  true       "文件"
@@ -540,7 +463,7 @@ func (this *VideoController) UploadFile() {
 		br.ErrMsg = "初始化OSS服务失败"
 		return
 	}
-	mp3Url, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
+	imageUrl, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
 	if err != nil {
 		br.Msg = "图片上传失败"
 		br.ErrMsg = "图片上传失败,Err:" + err.Error()
@@ -548,7 +471,7 @@ func (this *VideoController) UploadFile() {
 	}
 	base := path.Base(h.Filename)
 	resp := new(response.MediaUploadResp)
-	resp.Url = mp3Url
+	resp.Url = imageUrl
 	resp.FileName = base
 	br.Data = resp
 	br.Msg = "上传成功"
@@ -556,17 +479,127 @@ func (this *VideoController) UploadFile() {
 	br.Success = true
 }
 
-type Chunk struct {
-	Filename    string
-	UniqueCode  string
-	ChunkNumber int
-	TotalChunks int
-	Data        []byte
+// BoxHeader represents the header of an ISO BMFF box.
+type BoxHeader struct {
+	Size   uint32
+	Type   [4]byte
+	Size64 uint64
 }
 
-var chunksMap = make(map[string][]Chunk)
+// getHeaderBoxInfo parses the box header from the provided byte slice.
+func getHeaderBoxInfo(data []byte) BoxHeader {
+	var header BoxHeader
+	header.Size = binary.BigEndian.Uint32(data[0:4])
+	copy(header.Type[:], data[4:8])
+	if header.Size == 1 {
+		header.Size64 = binary.BigEndian.Uint64(data[8:16])
+	}
+	return header
+}
 
-// getFourccType 获取信息头类型
-func getFourccType(boxHeader BoxHeader) (fourccType string) {
-	return string(boxHeader.FourccType[:])
+// getFourccType returns the FourCC type as a string.
+func getFourccType(header BoxHeader) string {
+	return string(header.Type[:])
+}
+
+// readBox reads the entire box data from the reader at the given offset.
+func readBox(reader io.ReaderAt, offset int64, size uint64) ([]byte, error) {
+	boxData := make([]byte, size)
+	_, err := reader.ReadAt(boxData, offset)
+	if err != nil {
+		return nil, err
+	}
+	return boxData, nil
+}
+
+// findBox recursively finds a box of the specified type within the given box data.
+func findBox(boxData []byte, boxType string) ([]byte, error) {
+	var offset uint32 = 0
+	for offset < uint32(len(boxData)) {
+		header := getHeaderBoxInfo(boxData[offset:])
+		size := uint64(header.Size)
+		if header.Size == 1 {
+			size = header.Size64
+		}
+		if getFourccType(header) == boxType {
+			return boxData[offset : offset+uint32(size)], nil
+		}
+		offset += uint32(size)
+	}
+	return nil, fmt.Errorf("box type %s not found", boxType)
+}
+
+// GetMP4Duration reads the duration of an MP4 or M4A file from the provided reader.
+func GetMP4Duration(reader io.ReaderAt) (lengthOfTime int, err error) {
+	var info = make([]byte, 0x10)
+	var boxHeader BoxHeader
+	var offset int64 = 0
+
+	// 获取moov结构偏移
+	for {
+		_, err = reader.ReadAt(info, offset)
+		if err == io.EOF {
+			fmt.Println("Reached EOF without finding moov box.")
+			return 0, fmt.Errorf("moov box not found")
+		}
+		if err != nil {
+			return 0, fmt.Errorf("error reading at offset %d: %w", offset, err)
+		}
+
+		boxHeader = getHeaderBoxInfo(info)
+		fourccType := getFourccType(boxHeader)
+
+		if fourccType == "moov" {
+			fmt.Println("Found moov box at offset", offset)
+			break
+		}
+
+		nextOffset := int64(boxHeader.Size)
+		if fourccType == "mdat" && boxHeader.Size == 1 {
+			nextOffset = int64(boxHeader.Size64)
+		}
+		if nextOffset == 0 {
+			return 0, fmt.Errorf("box size is zero, which is invalid and likely means a parsing error")
+		}
+		offset += nextOffset
+	}
+
+	// 读取moov盒子数据
+	moovBoxData, err := readBox(reader, offset, uint64(boxHeader.Size))
+	if err != nil {
+		return 0, fmt.Errorf("error reading moov box at offset %d: %w", offset, err)
+	}
+
+	// 在moov盒子中查找mvhd或tkhd盒子
+	mvhdBox, err := findBox(moovBoxData, "mvhd")
+	if err != nil {
+		tkhdBox, err := findBox(moovBoxData, "tkhd")
+		if err != nil {
+			return 0, fmt.Errorf("neither mvhd nor tkhd box found in moov box")
+		}
+		mvhdBox = tkhdBox
+	}
+
+	// 解析mvhd或tkhd盒子中的timeScale和duration
+	var timeScaleOffset, durationOffset uint32
+	if getFourccType(getHeaderBoxInfo(mvhdBox)) == "mvhd" {
+		timeScaleOffset = 0x1C
+		durationOffset = 0x20
+	} else if getFourccType(getHeaderBoxInfo(mvhdBox)) == "tkhd" {
+		timeScaleOffset = 0x14
+		durationOffset = 0x18
+	} else {
+		return 0, fmt.Errorf("unsupported box type in moov box")
+	}
+
+	timeScale := binary.BigEndian.Uint32(mvhdBox[timeScaleOffset : timeScaleOffset+4])
+	duration := binary.BigEndian.Uint32(mvhdBox[durationOffset : durationOffset+4])
+
+	fmt.Printf("timeScale: %d, duration: %d\n", timeScale, duration)
+	if timeScale == 0 {
+		return 0, fmt.Errorf("timeScale is zero, division by zero is not possible")
+	}
+
+	lengthOfTime = int(duration / timeScale)
+	return
 }