Browse Source

支持视频格式扩展

kobe6258 4 tháng trước cách đây
mục cha
commit
d5a68bdc7f
2 tập tin đã thay đổi với 104 bổ sung128 xóa
  1. 15 2
      controllers/audio.go
  2. 89 126
      controllers/video.go

+ 15 - 2
controllers/audio.go

@@ -18,6 +18,13 @@ import (
 	"time"
 )
 
+var (
+	audioType = map[string]int{
+		"mp3": 1,
+		"m4a": 1,
+	}
+)
+
 type AudioController struct {
 	BaseAuthController
 }
@@ -50,12 +57,18 @@ func (this *AudioController) UploadAudio() {
 		return
 	}
 	ext := path.Ext(h.Filename)
-	lowcaseExt := strings.ToLower(ext)
-	if lowcaseExt != ".mp3" {
+	lowCaseExt := strings.ToLower(ext)
+	if _, ok := audioType[lowCaseExt]; !ok {
 		br.Msg = "音频格式不正确"
 		br.ErrMsg = "音频上传失败,Err:" + err.Error()
 		return
 	}
+
+	//if lowcaseExt != ".mp3" {
+	//	br.Msg = "音频格式不正确"
+	//	br.ErrMsg = "音频上传失败,Err:" + err.Error()
+	//	return
+	//}
 	dateDir := time.Now().Format("20060102")
 	uploadDir := utils.STATIC_DIR + "ht/audio" + dateDir
 	err = os.MkdirAll(uploadDir, utils.DIR_MOD)

+ 89 - 126
controllers/video.go

@@ -1,6 +1,7 @@
 package controllers
 
 import (
+	"bytes"
 	"encoding/binary"
 	"encoding/json"
 	"eta/eta_mini_crm_ht/models"
@@ -15,13 +16,13 @@ import (
 	"os"
 	"path"
 	"strconv"
+	"strings"
 	"time"
 )
 
 var (
 	videoType = map[string]int{
 		"mp4": 1,
-		"m4a": 1,
 	}
 )
 
@@ -57,7 +58,8 @@ func (this *VideoController) UploadVideo() {
 		return
 	}
 	ext := path.Ext(h.Filename)
-	if _, ok := videoType[ext]; !ok {
+	lowCaseExt := strings.ToLower(ext)
+	if _, ok := videoType[lowCaseExt]; !ok {
 		br.Msg = "视频格式不正确"
 		br.ErrMsg = "视频上传失败,Err:" + err.Error()
 		return
@@ -102,7 +104,7 @@ func (this *VideoController) UploadVideo() {
 		br.ErrMsg = "初始化OSS服务失败"
 		return
 	}
-	videoUrl, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
+	mp3Url, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
 	if err != nil {
 		br.Msg = "视频上传失败"
 		br.ErrMsg = "视频上传失败,Err:" + err.Error()
@@ -110,7 +112,7 @@ func (this *VideoController) UploadVideo() {
 	}
 	base := path.Base(h.Filename)
 	resp := new(response.MediaUploadResp)
-	resp.Url = videoUrl
+	resp.Url = mp3Url
 	resp.FileName = base
 	resp.DurationMillisecond = duration * 1000
 	br.Data = resp
@@ -402,6 +404,77 @@ 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       "文件"
@@ -463,7 +536,7 @@ func (this *VideoController) UploadFile() {
 		br.ErrMsg = "初始化OSS服务失败"
 		return
 	}
-	imageUrl, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
+	mp3Url, err := ossClient.UploadFile("", fpath, savePdfToOssPath)
 	if err != nil {
 		br.Msg = "图片上传失败"
 		br.ErrMsg = "图片上传失败,Err:" + err.Error()
@@ -471,7 +544,7 @@ func (this *VideoController) UploadFile() {
 	}
 	base := path.Base(h.Filename)
 	resp := new(response.MediaUploadResp)
-	resp.Url = imageUrl
+	resp.Url = mp3Url
 	resp.FileName = base
 	br.Data = resp
 	br.Msg = "上传成功"
@@ -479,127 +552,17 @@ func (this *VideoController) UploadFile() {
 	br.Success = true
 }
 
-// BoxHeader represents the header of an ISO BMFF box.
-type BoxHeader struct {
-	Size   uint32
-	Type   [4]byte
-	Size64 uint64
-}
-
-// 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 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)
+type Chunk struct {
+	Filename    string
+	UniqueCode  string
+	ChunkNumber int
+	TotalChunks int
+	Data        []byte
 }
 
-// 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])
+var chunksMap = make(map[string][]Chunk)
 
-	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
+// getFourccType 获取信息头类型
+func getFourccType(boxHeader BoxHeader) (fourccType string) {
+	return string(boxHeader.FourccType[:])
 }