audio.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. package controllers
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/gin-gonic/gin"
  6. "gorm.io/gorm"
  7. "io"
  8. "mime/multipart"
  9. "os"
  10. "path"
  11. "speechAnalysis/constvar"
  12. "speechAnalysis/extend/code"
  13. "speechAnalysis/extend/util"
  14. "speechAnalysis/models"
  15. "speechAnalysis/pkg/logx"
  16. "speechAnalysis/request"
  17. "speechAnalysis/response"
  18. "speechAnalysis/service"
  19. "speechAnalysis/utils/upload"
  20. "strings"
  21. "time"
  22. )
  23. type AudioCtl struct{}
  24. // Upload
  25. // @Tags 音频
  26. // @Summary 上传音频
  27. // @Produce application/json
  28. // @Param file formData file false "音频文件"
  29. // @Param files formData []file false "多个音频文件"
  30. // @Success 200 {object} util.Response "成功"
  31. // @Router /api-sa/v1/audio/upload [post]
  32. func (slf AudioCtl) Upload(c *gin.Context) {
  33. f := func(header *multipart.FileHeader) error {
  34. logFormat := "%s,%s "
  35. filename := path.Base(header.Filename)
  36. arr := strings.Split(filename, "_")
  37. if len(arr) != 6 {
  38. //util.ResponseFormat(c, code.RequestParamError, "文件名称错误")
  39. return errors.New(fmt.Sprintf(logFormat, filename, "文件名称错误"))
  40. }
  41. _, err := models.NewAudioSearch().SetName(filename).First()
  42. if err != gorm.ErrRecordNotFound {
  43. //util.ResponseFormat(c, code.RequestParamError, "重复上传")
  44. return errors.New(fmt.Sprintf(logFormat, filename, "重复上传"))
  45. }
  46. oss := upload.NewOss()
  47. filePath, filename, uploadErr := oss.UploadFile(header)
  48. if uploadErr != nil {
  49. logx.Errorf("upload audio err: %v", err)
  50. //util.ResponseFormat(c, code.RequestParamError, "上传失败")
  51. return errors.New(fmt.Sprintf(logFormat, filename, "上传失败"))
  52. }
  53. timeStr := arr[4] + strings.Split(arr[5], ".")[0]
  54. t, err := time.ParseInLocation("20060102150405", timeStr, time.Local)
  55. if err != nil {
  56. //util.ResponseFormat(c, code.RequestParamError, "时间格式不对")
  57. return errors.New(fmt.Sprintf(logFormat, filename, "上传失败"))
  58. }
  59. audio := &models.Audio{
  60. Name: filename,
  61. Size: header.Size,
  62. FilePath: filePath,
  63. AudioStatus: constvar.AudioStatusUploadOk,
  64. LocomotiveNumber: arr[0],
  65. TrainNumber: arr[1],
  66. DriverNumber: arr[2],
  67. Station: arr[3],
  68. OccurrenceAt: t,
  69. IsFollowed: 0,
  70. }
  71. if err = models.NewAudioSearch().Create(audio); err != nil {
  72. //util.ResponseFormat(c, code.SaveFail, "上传失败")
  73. return errors.New(fmt.Sprintf(logFormat, filename, "上传失败"))
  74. }
  75. go func() {
  76. var trainInfoNames = []string{arr[0], arr[1], arr[3]}
  77. var (
  78. info *models.TrainInfo
  79. err error
  80. parent models.TrainInfo
  81. )
  82. for i := 0; i < 3; i++ {
  83. name := trainInfoNames[i]
  84. class := constvar.Class(i + 1)
  85. info, err = models.NewTrainInfoSearch().SetName(name).SetClass(class).First()
  86. if err == gorm.ErrRecordNotFound {
  87. info = &models.TrainInfo{
  88. Name: name,
  89. Class: class,
  90. ParentID: parent.ID,
  91. }
  92. _ = models.NewTrainInfoSearch().Create(info)
  93. }
  94. parent = *info
  95. }
  96. }()
  97. return nil
  98. }
  99. var headers []*multipart.FileHeader
  100. _, header, _ := c.Request.FormFile("file")
  101. if header != nil {
  102. headers = append(headers, header)
  103. }
  104. if len(c.Request.MultipartForm.File["files"]) > 0 {
  105. headers = c.Request.MultipartForm.File["files"]
  106. }
  107. var errs []error
  108. for _, h := range headers {
  109. if e := f(h); e != nil {
  110. errs = append(errs, e)
  111. }
  112. }
  113. if len(errs) > 0 {
  114. var r strings.Builder
  115. for _, e := range errs {
  116. r.WriteString(e.Error())
  117. }
  118. util.ResponseFormat(c, code.RequestParamError, r.String())
  119. return
  120. } else {
  121. util.ResponseFormat(c, code.Success, "添加成功")
  122. return
  123. }
  124. }
  125. func (slf AudioCtl) ParamsCheck(filename string) (err error) {
  126. arr := strings.Split(filename, "_")
  127. if len(arr) != 6 {
  128. return errors.New("文件格式错误")
  129. }
  130. return nil
  131. }
  132. // TrainInfoList
  133. // @Tags 音频
  134. // @Summary 获取火车信息
  135. // @Produce application/json
  136. // @Param object query request.GetTrainInfoList true "参数"
  137. // @Success 200 {object} util.ResponseList{data=[]models.TrainInfo} "成功"
  138. // @Router /api-sa/v1/audio/trainInfoList [get]
  139. func (slf AudioCtl) TrainInfoList(c *gin.Context) {
  140. var params request.GetTrainInfoList
  141. if err := c.ShouldBindQuery(&params); err != nil {
  142. util.ResponseFormat(c, code.RequestParamError, err.Error())
  143. return
  144. }
  145. if !params.PageInfo.Check() {
  146. util.ResponseFormat(c, code.RequestParamError, "分页参数错误")
  147. return
  148. }
  149. list, total, err := models.NewTrainInfoSearch().
  150. SetPage(params.Page, params.PageSize).
  151. SetClass(params.Class).
  152. SetParentId(params.ParentID).
  153. Find()
  154. if err != nil {
  155. util.ResponseFormat(c, code.RequestParamError, "查找失败")
  156. return
  157. }
  158. util.ResponseFormatList(c, code.Success, list, total)
  159. }
  160. // List
  161. // @Tags 音频
  162. // @Summary 音频分析检索
  163. // @Produce application/json
  164. // @Param object query request.GetAudioList true "参数"
  165. // @Success 200 {object} util.ResponseList{data=[]models.Audio} "成功"
  166. // @Router /api-sa/v1/audio/list [get]
  167. func (slf AudioCtl) List(c *gin.Context) {
  168. var params request.GetAudioList
  169. if err := c.ShouldBindQuery(&params); err != nil {
  170. util.ResponseFormat(c, code.RequestParamError, err.Error())
  171. return
  172. }
  173. if !params.PageInfo.Check() {
  174. util.ResponseFormat(c, code.RequestParamError, "分页参数错误")
  175. return
  176. }
  177. list, total, err := models.NewAudioSearch().
  178. SetPage(params.Page, params.PageSize).
  179. SetKeyword(params.Keyword).
  180. SetLocomotiveNumber(params.LocomotiveNumber).
  181. SetTrainNumber(params.TrainNumber).
  182. SetDriverNumber(params.DriverNumber).
  183. SetStation(params.StationNumber).
  184. SetBeginTime(params.BeginTime).
  185. SetEndTime(params.EndTime).
  186. SetIsFollowed(params.IsFollowed).
  187. SetAudioStatusList(params.StatusList).
  188. Find()
  189. if err != nil {
  190. util.ResponseFormat(c, code.RequestParamError, "查找失败")
  191. return
  192. }
  193. util.ResponseFormatList(c, code.Success, list, total)
  194. }
  195. // Process
  196. // @Tags 音频
  197. // @Summary 处理音频
  198. // @Produce application/json
  199. // @Param object body request.ProcessAudio true "参数"
  200. // @Success 200 {object} util.Response "成功"
  201. // @Router /api-sa/v1/audio/process [post]
  202. func (slf AudioCtl) Process(c *gin.Context) {
  203. var params request.ProcessAudio
  204. if err := c.ShouldBind(&params); err != nil {
  205. util.ResponseFormat(c, code.RequestParamError, err.Error())
  206. return
  207. }
  208. err := service.Process(params.ID)
  209. if err != nil {
  210. util.ResponseFormat(c, code.InternalError, err.Error())
  211. return
  212. }
  213. util.ResponseFormat(c, code.UpdateSuccess, "成功")
  214. }
  215. // AudioInfo
  216. // @Tags 音频
  217. // @Summary 音频详情,含解析结果
  218. // @Produce application/json
  219. // @Param object query request.ProcessAudio true "参数"
  220. // @Success 200 {object} util.Response{data=models.Audio} "成功"
  221. // @Router /api-sa/v1/audio/info [get]
  222. func (slf AudioCtl) AudioInfo(c *gin.Context) {
  223. var params request.ProcessAudio
  224. if err := c.ShouldBindQuery(&params); err != nil {
  225. util.ResponseFormat(c, code.RequestParamError, err.Error())
  226. return
  227. }
  228. audio, err := models.NewAudioSearch().SetID(params.ID).First()
  229. if err != nil {
  230. util.ResponseFormat(c, code.InternalError, "请求失败")
  231. return
  232. }
  233. audioText, err := models.NewAudioTextSearch().SetAudioID(audio.ID).First()
  234. if err == nil {
  235. audio.AudioText = audioText.AudioText
  236. }
  237. util.ResponseFormat(c, code.UpdateSuccess, audio)
  238. }
  239. // AudioDownload
  240. // @Tags 音频
  241. // @Summary 音频下载
  242. // @Produce application/json
  243. // @Param object query request.ProcessAudio true "参数"
  244. // @Success 200 {object} util.Response{data=models.Audio} "成功"
  245. // @Router /api-sa/v1/audio/download [get]
  246. func (slf AudioCtl) AudioDownload(c *gin.Context) {
  247. var params request.ProcessAudio
  248. if err := c.ShouldBindQuery(&params); err != nil {
  249. util.ResponseFormat(c, code.RequestParamError, err.Error())
  250. return
  251. }
  252. audio, err := models.NewAudioSearch().SetID(params.ID).First()
  253. if err != nil {
  254. util.ResponseFormat(c, code.InternalError, "查询失败")
  255. return
  256. }
  257. if audio.FilePath == "" {
  258. util.ResponseFormat(c, code.InternalError, "查询失败")
  259. return
  260. }
  261. file, err := os.Open(audio.FilePath)
  262. if err != nil {
  263. util.ResponseFormat(c, code.InternalError, "文件打开失败")
  264. return
  265. }
  266. defer file.Close()
  267. fileInfo, err := file.Stat()
  268. if err != nil {
  269. util.ResponseFormat(c, code.InternalError, "获取文件信息失败")
  270. return
  271. }
  272. c.Header("Content-Disposition", "inline; filename="+audio.Name) // 在浏览器中直接打开
  273. c.Header("Content-Length", fmt.Sprint(fileInfo.Size()))
  274. c.Header("Content-Type", "audio/mpeg") // 设置音频文件类型
  275. if _, err := io.Copy(c.Writer, file); err != nil {
  276. util.ResponseFormat(c, code.InternalError, "文件传输失败")
  277. return
  278. }
  279. }
  280. // BatchProcess
  281. // @Tags 音频
  282. // @Summary 批量处理音频
  283. // @Produce application/json
  284. // @Param object body request.BatchProcessAudio true "参数"
  285. // @Success 200 {object} util.Response "成功"
  286. // @Router /api-sa/v1/audio/batchProcess [post]
  287. func (slf AudioCtl) BatchProcess(c *gin.Context) {
  288. var params request.BatchProcessAudio
  289. if err := c.ShouldBind(&params); err != nil {
  290. util.ResponseFormat(c, code.RequestParamError, err.Error())
  291. return
  292. }
  293. var failedNumber int
  294. for _, audioID := range params.IDs {
  295. err := service.Process(audioID)
  296. if err != nil {
  297. logx.Errorf("%v,编号: %v", err.Error(), audioID)
  298. failedNumber++
  299. continue
  300. }
  301. }
  302. if failedNumber == 0 {
  303. util.ResponseFormat(c, code.UpdateSuccess, "成功")
  304. return
  305. } else if failedNumber < len(params.IDs) {
  306. util.ResponseFormat(c, code.RequestParamError, "部分处理失败")
  307. return
  308. } else {
  309. util.ResponseFormat(c, code.RequestParamError, "全部处理失败")
  310. return
  311. }
  312. }
  313. // Delete
  314. // @Tags 音频
  315. // @Summary 删除音频
  316. // @Produce application/json
  317. // @Param object body request.ProcessAudio true "参数"
  318. // @Success 200 {object} util.Response "成功"
  319. // @Router /api-sa/v1/audio/delete [delete]
  320. func (slf AudioCtl) Delete(c *gin.Context) {
  321. var params request.ProcessAudio
  322. if err := c.ShouldBind(&params); err != nil {
  323. util.ResponseFormat(c, code.RequestParamError, err.Error())
  324. return
  325. }
  326. audio, err := models.NewAudioSearch().SetID(params.ID).First()
  327. if err != nil {
  328. util.ResponseFormat(c, code.RequestParamError, "音频不存在")
  329. return
  330. }
  331. if audio.AudioStatus == constvar.AudioStatusProcessing || audio.AudioStatus == constvar.AudioStatusFinish {
  332. util.ResponseFormat(c, code.RequestParamError, "音频正在处理或者处理完成,不可删除")
  333. return
  334. }
  335. err = service.DeleteAudio(params.ID)
  336. if err != nil {
  337. util.ResponseFormat(c, code.InternalError, err.Error())
  338. return
  339. }
  340. go func() {
  341. err = os.Remove(audio.FilePath)
  342. if err != nil {
  343. logx.Warnf("remove file err:%v, file:%v", err, audio.FilePath)
  344. }
  345. }()
  346. util.ResponseFormat(c, code.DeleteSuccess, "成功")
  347. }
  348. // BatchDelete
  349. // @Tags 音频
  350. // @Summary 批量删除音频
  351. // @Produce application/json
  352. // @Param object body request.BatchProcessAudio true "参数"
  353. // @Success 200 {object} util.Response "成功"
  354. // @Router /api-sa/v1/audio/batchDelete [delete]
  355. func (slf AudioCtl) BatchDelete(c *gin.Context) {
  356. var params request.BatchProcessAudio
  357. if err := c.ShouldBind(&params); err != nil {
  358. util.ResponseFormat(c, code.RequestParamError, err.Error())
  359. return
  360. }
  361. audioList, err := models.NewAudioSearch().SetIDs(params.IDs).FindNotTotal()
  362. if err != nil {
  363. util.ResponseFormat(c, code.InternalError, "内部错误")
  364. return
  365. }
  366. for _, audio := range audioList {
  367. if audio.AudioStatus == constvar.AudioStatusProcessing || audio.AudioStatus == constvar.AudioStatusFinish {
  368. util.ResponseFormat(c, code.RequestParamError, "音频正在处理或者处理完成,不可删除")
  369. return
  370. }
  371. }
  372. err = service.BatchDeleteAudio(params.IDs)
  373. if err != nil {
  374. util.ResponseFormat(c, code.InternalError, err.Error())
  375. return
  376. }
  377. go func() {
  378. for _, audio := range audioList {
  379. err = os.Remove(audio.FilePath)
  380. if err != nil {
  381. logx.Warnf("remove file err:%v, file:%v", err, audio.FilePath)
  382. }
  383. }
  384. }()
  385. util.ResponseFormat(c, code.DeleteSuccess, "成功")
  386. }
  387. // Follow
  388. // @Tags 音频
  389. // @Summary 关注/取消关注
  390. // @Produce application/json
  391. // @Param object body request.FollowReq true "参数"
  392. // @Success 200 {object} util.Response{data=response.FollowResp} "成功"
  393. // @Router /api-sa/v1/audio/follow [post]
  394. func (slf AudioCtl) Follow(c *gin.Context) {
  395. var params request.ProcessAudio
  396. if err := c.ShouldBind(&params); err != nil {
  397. util.ResponseFormat(c, code.RequestParamError, err.Error())
  398. return
  399. }
  400. followStatus, err := service.Follow(params.ID)
  401. if err != nil {
  402. util.ResponseFormat(c, code.InternalError, err.Error())
  403. return
  404. }
  405. resp := response.FollowResp{FollowStatus: followStatus}
  406. util.ResponseFormat(c, code.UpdateSuccess, resp)
  407. }