| | |
| | | "github.com/gin-gonic/gin" |
| | | "gorm.io/gorm" |
| | | "path" |
| | | "speechAnalysis/conf" |
| | | "speechAnalysis/constvar" |
| | | "speechAnalysis/extend/code" |
| | | "speechAnalysis/extend/util" |
| | |
| | | return |
| | | } |
| | | |
| | | audio, err := models.NewAudioSearch().SetID(params.ID).First() |
| | | |
| | | err := service.Process(params.ID) |
| | | if err != nil { |
| | | util.ResponseFormat(c, code.RequestParamError, "查找音频失败") |
| | | util.ResponseFormat(c, code.InternalError, err.Error()) |
| | | return |
| | | } |
| | | |
| | | if audio.AudioStatus != constvar.AudioStatusUploadOk && audio.AudioStatus != constvar.AudioStatusFailed { |
| | | util.ResponseFormat(c, code.RequestParamError, "状态不正确") |
| | | return |
| | | } |
| | | |
| | | err = models.NewAudioSearch().SetID(params.ID).UpdateByMap(map[string]interface{}{"audio_status": constvar.AudioStatusProcessing}) |
| | | if err != nil { |
| | | util.ResponseFormat(c, code.RequestParamError, "处理失败") |
| | | return |
| | | } |
| | | |
| | | go func() { |
| | | resp, err := service.AnalysisAudio(audio.FilePath, conf.AanlysisConf.Url) |
| | | if err != nil { |
| | | logx.Errorf("err when AnalysisAudio:%v", err) |
| | | _ = models.NewAudioSearch().SetID(params.ID).UpdateByMap(map[string]interface{}{"audio_status": constvar.AudioStatusFailed}) |
| | | return |
| | | } |
| | | if resp.Code != 0 { |
| | | logx.Errorf("AnalysisAudio error return:%v", resp) |
| | | _ = models.NewAudioSearch().SetID(params.ID).UpdateByMap(map[string]interface{}{"audio_status": constvar.AudioStatusFailed}) |
| | | return |
| | | } |
| | | logx.Infof("AnalysisAudio result: %v", resp) |
| | | err = models.WithTransaction(func(db *gorm.DB) error { |
| | | err = models.NewAudioSearch().SetID(params.ID).UpdateByMap(map[string]interface{}{"audio_status": constvar.AudioStatusFinish}) |
| | | if err != nil { |
| | | return err |
| | | } |
| | | err = models.NewAudioTextSearch().Save(&models.AudioText{ |
| | | AudioID: audio.ID, |
| | | AudioText: resp.Result, |
| | | Score: resp.Score, |
| | | }) |
| | | return err |
| | | }) |
| | | if err != nil { |
| | | logx.Infof("AnalysisAudio success but update record failed: %v", err) |
| | | return |
| | | } |
| | | }() |
| | | |
| | | util.ResponseFormat(c, code.UpdateSuccess, "成功") |
| | | } |
| | | |
| | | // BatchProcess |
| | | // @Tags 音频 |
| | | // @Summary 批量处理音频 |
| | | // @Produce application/json |
| | | // @Param object body request.BatchProcessAudio true "音频信息" |
| | | // @Success 200 {object} util.Response "成功" |
| | | // @Router /api-sa/v1/audio/batchProcess [post] |
| | | func (slf AudioCtl) BatchProcess(c *gin.Context) { |
| | | var params request.BatchProcessAudio |
| | | if err := c.ShouldBind(¶ms); err != nil { |
| | | util.ResponseFormat(c, code.RequestParamError, err.Error()) |
| | | return |
| | | } |
| | | |
| | | var failedNumber int |
| | | for _, audioID := range params.IDs { |
| | | err := service.Process(audioID) |
| | | if err != nil { |
| | | logx.Errorf("%v,编号: %v", err.Error(), audioID) |
| | | failedNumber++ |
| | | continue |
| | | } |
| | | } |
| | | |
| | | if failedNumber == 0 { |
| | | util.ResponseFormat(c, code.UpdateSuccess, "成功") |
| | | return |
| | | } else if failedNumber < len(params.IDs) { |
| | | util.ResponseFormat(c, code.RequestParamError, "部分处理失败") |
| | | return |
| | | } else { |
| | | util.ResponseFormat(c, code.RequestParamError, "全部处理失败") |
| | | return |
| | | } |
| | | } |
| | | |
| | | // Delete |
| | | // @Tags 音频 |
| | | // @Summary 删除音频 |
| | | // @Produce application/json |
| | | // @Param object body request.ProcessAudio true "音频信息" |
| | | // @Success 200 {object} util.Response "成功" |
| | | // @Router /api-sa/v1/audio/delete [post] |
| | | func (slf AudioCtl) Delete(c *gin.Context) { |
| | | var params request.ProcessAudio |
| | | if err := c.ShouldBind(¶ms); err != nil { |
| | | util.ResponseFormat(c, code.RequestParamError, err.Error()) |
| | | return |
| | | } |
| | | |
| | | err := service.DeleteAudio(params.ID) |
| | | if err != nil { |
| | | util.ResponseFormat(c, code.InternalError, err.Error()) |
| | | return |
| | | } |
| | | |
| | | util.ResponseFormat(c, code.DeleteSuccess, "成功") |
| | | } |
| | | |
| | | // BatchDelete |
| | | // @Tags 音频 |
| | | // @Summary 批量删除音频 |
| | | // @Produce application/json |
| | | // @Param object body request.BatchProcessAudio true "音频信息" |
| | | // @Success 200 {object} util.Response "成功" |
| | | // @Router /api-sa/v1/audio/batchDelete [post] |
| | | func (slf AudioCtl) BatchDelete(c *gin.Context) { |
| | | var params request.BatchProcessAudio |
| | | if err := c.ShouldBind(¶ms); err != nil { |
| | | util.ResponseFormat(c, code.RequestParamError, err.Error()) |
| | | return |
| | | } |
| | | |
| | | err := service.BatchDeleteAudio(params.IDs) |
| | | if err != nil { |
| | | util.ResponseFormat(c, code.InternalError, err.Error()) |
| | | return |
| | | } |
| | | |
| | | util.ResponseFormat(c, code.DeleteSuccess, "成功") |
| | | } |
| | |
| | | "host": "{{.Host}}", |
| | | "basePath": "{{.BasePath}}", |
| | | "paths": { |
| | | "/api-sa/v1/audio/batchDelete": { |
| | | "post": { |
| | | "produces": [ |
| | | "application/json" |
| | | ], |
| | | "tags": [ |
| | | "音频" |
| | | ], |
| | | "summary": "批量删除音频", |
| | | "parameters": [ |
| | | { |
| | | "description": "音频信息", |
| | | "name": "object", |
| | | "in": "body", |
| | | "required": true, |
| | | "schema": { |
| | | "$ref": "#/definitions/request.BatchProcessAudio" |
| | | } |
| | | } |
| | | ], |
| | | "responses": { |
| | | "200": { |
| | | "description": "成功", |
| | | "schema": { |
| | | "$ref": "#/definitions/util.Response" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "/api-sa/v1/audio/batchProcess": { |
| | | "post": { |
| | | "produces": [ |
| | | "application/json" |
| | | ], |
| | | "tags": [ |
| | | "音频" |
| | | ], |
| | | "summary": "批量处理音频", |
| | | "parameters": [ |
| | | { |
| | | "description": "音频信息", |
| | | "name": "object", |
| | | "in": "body", |
| | | "required": true, |
| | | "schema": { |
| | | "$ref": "#/definitions/request.BatchProcessAudio" |
| | | } |
| | | } |
| | | ], |
| | | "responses": { |
| | | "200": { |
| | | "description": "成功", |
| | | "schema": { |
| | | "$ref": "#/definitions/util.Response" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "/api-sa/v1/audio/delete": { |
| | | "post": { |
| | | "produces": [ |
| | | "application/json" |
| | | ], |
| | | "tags": [ |
| | | "音频" |
| | | ], |
| | | "summary": "删除音频", |
| | | "parameters": [ |
| | | { |
| | | "description": "音频信息", |
| | | "name": "object", |
| | | "in": "body", |
| | | "required": true, |
| | | "schema": { |
| | | "$ref": "#/definitions/request.ProcessAudio" |
| | | } |
| | | } |
| | | ], |
| | | "responses": { |
| | | "200": { |
| | | "description": "成功", |
| | | "schema": { |
| | | "$ref": "#/definitions/util.Response" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "/api-sa/v1/audio/list": { |
| | | "get": { |
| | | "produces": [ |
| | |
| | | } |
| | | } |
| | | }, |
| | | "request.BatchProcessAudio": { |
| | | "type": "object", |
| | | "required": [ |
| | | "ids" |
| | | ], |
| | | "properties": { |
| | | "ids": { |
| | | "type": "array", |
| | | "items": { |
| | | "type": "integer" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "request.ProcessAudio": { |
| | | "type": "object", |
| | | "required": [ |
| | |
| | | "contact": {} |
| | | }, |
| | | "paths": { |
| | | "/api-sa/v1/audio/batchDelete": { |
| | | "post": { |
| | | "produces": [ |
| | | "application/json" |
| | | ], |
| | | "tags": [ |
| | | "音频" |
| | | ], |
| | | "summary": "批量删除音频", |
| | | "parameters": [ |
| | | { |
| | | "description": "音频信息", |
| | | "name": "object", |
| | | "in": "body", |
| | | "required": true, |
| | | "schema": { |
| | | "$ref": "#/definitions/request.BatchProcessAudio" |
| | | } |
| | | } |
| | | ], |
| | | "responses": { |
| | | "200": { |
| | | "description": "成功", |
| | | "schema": { |
| | | "$ref": "#/definitions/util.Response" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "/api-sa/v1/audio/batchProcess": { |
| | | "post": { |
| | | "produces": [ |
| | | "application/json" |
| | | ], |
| | | "tags": [ |
| | | "音频" |
| | | ], |
| | | "summary": "批量处理音频", |
| | | "parameters": [ |
| | | { |
| | | "description": "音频信息", |
| | | "name": "object", |
| | | "in": "body", |
| | | "required": true, |
| | | "schema": { |
| | | "$ref": "#/definitions/request.BatchProcessAudio" |
| | | } |
| | | } |
| | | ], |
| | | "responses": { |
| | | "200": { |
| | | "description": "成功", |
| | | "schema": { |
| | | "$ref": "#/definitions/util.Response" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "/api-sa/v1/audio/delete": { |
| | | "post": { |
| | | "produces": [ |
| | | "application/json" |
| | | ], |
| | | "tags": [ |
| | | "音频" |
| | | ], |
| | | "summary": "删除音频", |
| | | "parameters": [ |
| | | { |
| | | "description": "音频信息", |
| | | "name": "object", |
| | | "in": "body", |
| | | "required": true, |
| | | "schema": { |
| | | "$ref": "#/definitions/request.ProcessAudio" |
| | | } |
| | | } |
| | | ], |
| | | "responses": { |
| | | "200": { |
| | | "description": "成功", |
| | | "schema": { |
| | | "$ref": "#/definitions/util.Response" |
| | | } |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "/api-sa/v1/audio/list": { |
| | | "get": { |
| | | "produces": [ |
| | |
| | | } |
| | | } |
| | | }, |
| | | "request.BatchProcessAudio": { |
| | | "type": "object", |
| | | "required": [ |
| | | "ids" |
| | | ], |
| | | "properties": { |
| | | "ids": { |
| | | "type": "array", |
| | | "items": { |
| | | "type": "integer" |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | "request.ProcessAudio": { |
| | | "type": "object", |
| | | "required": [ |
| | |
| | | updatedAt: |
| | | type: string |
| | | type: object |
| | | request.BatchProcessAudio: |
| | | properties: |
| | | ids: |
| | | items: |
| | | type: integer |
| | | type: array |
| | | required: |
| | | - ids |
| | | type: object |
| | | request.ProcessAudio: |
| | | properties: |
| | | id: |
| | |
| | | info: |
| | | contact: {} |
| | | paths: |
| | | /api-sa/v1/audio/batchDelete: |
| | | post: |
| | | parameters: |
| | | - description: 音频信息 |
| | | in: body |
| | | name: object |
| | | required: true |
| | | schema: |
| | | $ref: '#/definitions/request.BatchProcessAudio' |
| | | produces: |
| | | - application/json |
| | | responses: |
| | | "200": |
| | | description: 成功 |
| | | schema: |
| | | $ref: '#/definitions/util.Response' |
| | | summary: 批量删除音频 |
| | | tags: |
| | | - 音频 |
| | | /api-sa/v1/audio/batchProcess: |
| | | post: |
| | | parameters: |
| | | - description: 音频信息 |
| | | in: body |
| | | name: object |
| | | required: true |
| | | schema: |
| | | $ref: '#/definitions/request.BatchProcessAudio' |
| | | produces: |
| | | - application/json |
| | | responses: |
| | | "200": |
| | | description: 成功 |
| | | schema: |
| | | $ref: '#/definitions/util.Response' |
| | | summary: 批量处理音频 |
| | | tags: |
| | | - 音频 |
| | | /api-sa/v1/audio/delete: |
| | | post: |
| | | parameters: |
| | | - description: 音频信息 |
| | | in: body |
| | | name: object |
| | | required: true |
| | | schema: |
| | | $ref: '#/definitions/request.ProcessAudio' |
| | | produces: |
| | | - application/json |
| | | responses: |
| | | "200": |
| | | description: 成功 |
| | | schema: |
| | | $ref: '#/definitions/util.Response' |
| | | summary: 删除音频 |
| | | tags: |
| | | - 音频 |
| | | /api-sa/v1/audio/list: |
| | | get: |
| | | parameters: |
| | |
| | | PageSize int |
| | | Orm *gorm.DB |
| | | Keyword string |
| | | IDs []uint |
| | | } |
| | | ) |
| | | |
| | |
| | | |
| | | func (slf *AudioSearch) SetID(id uint) *AudioSearch { |
| | | slf.ID = id |
| | | return slf |
| | | } |
| | | |
| | | func (slf *AudioSearch) SetIDs(ids []uint) *AudioSearch { |
| | | slf.IDs = ids |
| | | return slf |
| | | } |
| | | |
| | |
| | | db = db.Where("station_number like ?", slf.StationNumber) |
| | | } |
| | | |
| | | if len(slf.IDs) > 0 { |
| | | db = db.Where("id in ?", slf.IDs) |
| | | } |
| | | |
| | | return db |
| | | } |
| | | |
| | |
| | | func (slf *AudioSearch) Delete() error { |
| | | var db = slf.build() |
| | | |
| | | if err := db.Unscoped().Delete(&Audio{}).Error; err != nil { |
| | | if err := db.Delete(&Audio{}).Error; err != nil { |
| | | return err |
| | | } |
| | | |
| | |
| | | PageNum int |
| | | PageSize int |
| | | Orm *gorm.DB |
| | | AudioIDs []uint |
| | | } |
| | | ) |
| | | |
| | |
| | | return slf |
| | | } |
| | | |
| | | func (slf *AudioTextSearch) SetAudioIDs(ids []uint) *AudioTextSearch { |
| | | slf.AudioIDs = ids |
| | | return slf |
| | | } |
| | | |
| | | func (slf *AudioTextSearch) build() *gorm.DB { |
| | | var db = slf.Orm.Table(slf.TableName()) |
| | | |
| | |
| | | |
| | | if slf.Order != "" { |
| | | db = db.Order(slf.Order) |
| | | } |
| | | |
| | | if len(slf.AudioIDs) > 0 { |
| | | db = db.Where("audio_id in ?", slf.AudioIDs) |
| | | } |
| | | |
| | | return db |
| | |
| | | func (slf *AudioTextSearch) Save(record *AudioText) error { |
| | | var db = slf.build() |
| | | |
| | | if err := db.Omit("CreatedAt").Save(record).Error; err != nil { |
| | | if err := db.Save(record).Error; err != nil { |
| | | return fmt.Errorf("save err: %v, record: %+v", err, record) |
| | | } |
| | | |
| | |
| | | func (slf *AudioTextSearch) Delete() error { |
| | | var db = slf.build() |
| | | |
| | | if err := db.Unscoped().Delete(&AudioText{}).Error; err != nil { |
| | | if err := db.Delete(&AudioText{}).Error; err != nil { |
| | | return err |
| | | } |
| | | |
| | |
| | | type ProcessAudio struct { |
| | | ID uint `json:"id" binding:"required"` |
| | | } |
| | | |
| | | type BatchProcessAudio struct { |
| | | IDs []uint `json:"ids" binding:"required"` |
| | | } |
| | |
| | | |
| | | urlPrefix := "/api-sa/v1" |
| | | |
| | | // 组织管理 |
| | | // 音频管理 |
| | | AudioCtl := new(controllers.AudioCtl) |
| | | organizeAPI := r.Group(urlPrefix + "/audio") |
| | | { |
| | | organizeAPI.POST("upload", AudioCtl.Upload) // 上传音频 |
| | | organizeAPI.GET("list", AudioCtl.List) // 音频检索 |
| | | organizeAPI.POST("process", AudioCtl.Process) // 音频处理 |
| | | organizeAPI.POST("batchProcess", AudioCtl.BatchProcess) // 音频批量处理 |
| | | organizeAPI.POST("delete", AudioCtl.Delete) // 音频删除 |
| | | organizeAPI.POST("batchDelete", AudioCtl.BatchDelete) // 音频批量删除 |
| | | } |
| | | |
| | | return r |
New file |
| | |
| | | package service |
| | | |
| | | import ( |
| | | "errors" |
| | | "gorm.io/gorm" |
| | | "speechAnalysis/models" |
| | | "speechAnalysis/pkg/logx" |
| | | ) |
| | | |
| | | func DeleteAudio(audioId uint) (err error) { |
| | | err = models.WithTransaction(func(db *gorm.DB) error { |
| | | if err := models.NewAudioSearch().SetID(audioId).Delete(); err != nil { |
| | | return err |
| | | } |
| | | return models.NewAudioTextSearch().SetAudioID(audioId).Delete() |
| | | }) |
| | | if err != nil { |
| | | logx.Errorf("delete audio err: %v", err) |
| | | return errors.New("DB错误") |
| | | } |
| | | return nil |
| | | } |
| | | |
| | | func BatchDeleteAudio(audioIds []uint) (err error) { |
| | | if len(audioIds) == 0 { |
| | | return nil |
| | | } |
| | | err = models.WithTransaction(func(db *gorm.DB) error { |
| | | if err := models.NewAudioSearch().SetIDs(audioIds).Delete(); err != nil { |
| | | return err |
| | | } |
| | | return models.NewAudioTextSearch().SetAudioIDs(audioIds).Delete() |
| | | }) |
| | | if err != nil { |
| | | logx.Errorf("delete audio err: %v", err) |
| | | return errors.New("DB错误") |
| | | } |
| | | return nil |
| | | } |
| | |
| | | import ( |
| | | "bytes" |
| | | "encoding/json" |
| | | "errors" |
| | | "gorm.io/gorm" |
| | | "io" |
| | | "mime/multipart" |
| | | "net/http" |
| | | "os" |
| | | "speechAnalysis/conf" |
| | | "speechAnalysis/constvar" |
| | | "speechAnalysis/models" |
| | | "speechAnalysis/pkg/logx" |
| | | ) |
| | | |
| | | // Response 结构体用于存储响应体的内容 |
| | |
| | | |
| | | return |
| | | } |
| | | |
| | | func Process(audioId uint) (err error) { |
| | | audio, err := models.NewAudioSearch().SetID(audioId).First() |
| | | |
| | | if err != nil { |
| | | return errors.New("查找音频失败") |
| | | } |
| | | |
| | | if audio.AudioStatus != constvar.AudioStatusUploadOk && audio.AudioStatus != constvar.AudioStatusFailed { |
| | | return errors.New("状态不正确") |
| | | } |
| | | |
| | | err = models.NewAudioSearch().SetID(audioId).UpdateByMap(map[string]interface{}{"audio_status": constvar.AudioStatusProcessing}) |
| | | if err != nil { |
| | | return errors.New("DB错误") |
| | | } |
| | | |
| | | go func() { |
| | | resp, err := AnalysisAudio(audio.FilePath, conf.AanlysisConf.Url) |
| | | if err != nil { |
| | | logx.Errorf("err when AnalysisAudio:%v", err) |
| | | _ = models.NewAudioSearch().SetID(audioId).UpdateByMap(map[string]interface{}{"audio_status": constvar.AudioStatusFailed}) |
| | | return |
| | | } |
| | | if resp.Code != 0 { |
| | | logx.Errorf("AnalysisAudio error return:%v", resp) |
| | | _ = models.NewAudioSearch().SetID(audioId).UpdateByMap(map[string]interface{}{"audio_status": constvar.AudioStatusFailed}) |
| | | return |
| | | } |
| | | logx.Infof("AnalysisAudio result: %v", resp) |
| | | err = models.WithTransaction(func(db *gorm.DB) error { |
| | | err = models.NewAudioSearch().SetID(audioId).UpdateByMap(map[string]interface{}{"audio_status": constvar.AudioStatusFinish}) |
| | | if err != nil { |
| | | return err |
| | | } |
| | | err = models.NewAudioTextSearch().Save(&models.AudioText{ |
| | | AudioID: audio.ID, |
| | | AudioText: resp.Result, |
| | | Score: resp.Score, |
| | | }) |
| | | return err |
| | | }) |
| | | if err != nil { |
| | | logx.Infof("AnalysisAudio success but update record failed: %v", err) |
| | | return |
| | | } |
| | | }() |
| | | |
| | | return nil |
| | | } |