浏览代码

m4a格式时长

kobe6258 3 月之前
父节点
当前提交
c063c5d118
共有 2 个文件被更改,包括 72 次插入26 次删除
  1. 68 23
      controllers/audio.go
  2. 4 3
      go.mod

+ 68 - 23
controllers/audio.go

@@ -1,6 +1,7 @@
 package controllers
 
 import (
+	"encoding/binary"
 	"encoding/json"
 	"eta/eta_mini_crm_ht/models"
 	"eta/eta_mini_crm_ht/models/request"
@@ -11,6 +12,7 @@ import (
 	"fmt"
 	"github.com/rdlucklib/rdluck_tools/paging"
 	"github.com/tcolgate/mp3"
+	"mime/multipart"
 	"os"
 	"path"
 	"strconv"
@@ -63,12 +65,18 @@ func (this *AudioController) UploadAudio() {
 		br.ErrMsg = "音频上传失败,Err:" + err.Error()
 		return
 	}
+	var duration int
+	if lowCaseExt == ".m4a" {
 
-	//if lowcaseExt != ".mp3" {
-	//	br.Msg = "音频格式不正确"
-	//	br.ErrMsg = "音频上传失败,Err:" + err.Error()
-	//	return
-	//}
+	}
+	if lowCaseExt == ".mp3" {
+		duration, err = mp3Duration(f)
+	}
+	if err != nil {
+		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)
@@ -86,22 +94,6 @@ func (this *AudioController) UploadAudio() {
 		br.ErrMsg = "音频上传失败,Err:" + err.Error()
 		return
 	}
-	mp3File := mp3.NewDecoder(f)
-	if err != nil {
-		br.Msg = "音频上传失败"
-		br.ErrMsg = "解析音频时常失败,Err:" + err.Error()
-		return
-	}
-	var totalDuration time.Duration
-	skipped := 0
-	for {
-		frame := mp3.Frame{}
-		if err = mp3File.Decode(&frame, &skipped); err != nil {
-			break
-		}
-		totalDuration += frame.Duration()
-	}
-	duration := int(totalDuration.Milliseconds())
 
 	audioUploadDir := utils.RESOURCE_DIR + "audio/"
 	savePdfToOssPath := audioUploadDir + time.Now().Format("200601/20060102/")
@@ -124,6 +116,7 @@ func (this *AudioController) UploadAudio() {
 		br.ErrMsg = "音频上传失败,Err:" + err.Error()
 		return
 	}
+
 	base := path.Base(h.Filename)
 	resp := new(response.MediaUploadResp)
 	resp.Url = mp3Url
@@ -134,6 +127,59 @@ func (this *AudioController) UploadAudio() {
 	br.Ret = 200
 	br.Success = true
 }
+func mp3Duration(file multipart.File) (duration int, err error) {
+	mp3File := mp3.NewDecoder(file)
+
+	var totalDuration time.Duration
+	skipped := 0
+	for {
+		frame := mp3.Frame{}
+		if err = mp3File.Decode(&frame, &skipped); err != nil {
+			break
+		}
+		totalDuration += frame.Duration()
+	}
+	duration = int(totalDuration.Milliseconds())
+	return
+}
+func m4aDuration(file multipart.File) (duration int, err error) {
+	var info = make([]byte, 0x10)
+	var boxHeader BoxHeader
+	var offset int64 = 0
+	// 获取moov结构偏移
+	for {
+		_, err = file.ReadAt(info, offset)
+		if err != nil {
+			return
+		}
+		boxHeader = getHeaderBoxInfo(info)
+		fourccType := getFourccType(boxHeader)
+		if fourccType == "moov" {
+			break
+		}
+		// 有一部分mp4 mdat尺寸过大需要特殊处理
+		if fourccType == "mdat" {
+			if boxHeader.Size == 1 {
+				offset += int64(boxHeader.Size64)
+				continue
+			}
+		}
+		offset += int64(boxHeader.Size)
+	}
+	// 获取moov结构开头一部分
+	moovStartBytes := make([]byte, 0x100)
+	_, err = file.ReadAt(moovStartBytes, offset)
+	if err != nil {
+		return
+	}
+	// 定义timeScale与Duration偏移
+	timeScaleOffset := 0x1C
+	durationOffest := 0x20
+	timeScale := binary.BigEndian.Uint32(moovStartBytes[timeScaleOffset : timeScaleOffset+4])
+	Duration := binary.BigEndian.Uint32(moovStartBytes[durationOffest : durationOffest+4])
+	duration = int(Duration * 1000 / timeScale)
+	return
+}
 
 // AddAudio @Title 新增音频
 // @Description 新增音频
@@ -175,14 +221,13 @@ func (this *AudioController) AddAudio() {
 		return
 	}
 	var err error
-
 	audioInsert := &models.Media{
 		AuthorId:              req.AnalystId,
 		AuthorName:            req.AnalystName,
 		MediaType:             models.Audio,
 		Src:                   req.SrcUrl,
 		MediaName:             req.AudioName,
-		SourceType:            "mp3",
+		SourceType:            req.SrcUrl[strings.LastIndex(req.SrcUrl, ".")+1:],
 		MediaPlayMilliseconds: req.DurationMillisecond,
 		PermissionIds:         req.PermissionIds,
 		SendStatus:            models.UNSEND,

+ 4 - 3
go.mod

@@ -9,8 +9,11 @@ require (
 	github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
 	github.com/beego/bee/v2 v2.1.0
 	github.com/dgrijalva/jwt-go v3.2.0+incompatible
+	github.com/disintegration/imaging v1.6.2
+	github.com/gabriel-vasile/mimetype v1.4.7
 	github.com/go-redis/redis/v8 v8.11.5
 	github.com/go-sql-driver/mysql v1.8.1
+	github.com/google/uuid v1.6.0
 	github.com/minio/minio-go/v7 v7.0.74
 	github.com/olivere/elastic/v7 v7.0.32
 	github.com/rdlucklib/rdluck_tools v1.0.3
@@ -24,17 +27,15 @@ require (
 
 require (
 	filippo.io/edwards25519 v1.1.0 // indirect
+	github.com/abema/go-mp4 v1.3.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
 	github.com/cespare/xxhash/v2 v2.3.0 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
-	github.com/disintegration/imaging v1.6.2 // indirect
 	github.com/dustin/go-humanize v1.0.1 // indirect
 	github.com/fatih/structs v1.1.0 // indirect
-	github.com/gabriel-vasile/mimetype v1.4.7 // indirect
 	github.com/go-ini/ini v1.67.0 // indirect
 	github.com/goccy/go-json v0.10.3 // indirect
-	github.com/google/uuid v1.6.0 // indirect
 	github.com/hashicorp/golang-lru v0.5.4 // indirect
 	github.com/jmespath/go-jmespath v0.4.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect