audio.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package audio
  2. import (
  3. "bytes"
  4. "eta/eta_pub/utils"
  5. "fmt"
  6. "math"
  7. "os"
  8. "os/exec"
  9. "path"
  10. "strconv"
  11. "strings"
  12. )
  13. // ConvAudioDecibel 音频分贝转换(生成新的文件)
  14. func ConvAudioDecibel(inputFile string) (outputFile string, isConvDecibel bool, err error) {
  15. // 转换音频格式后的音频地址
  16. convAudioPath := inputFile
  17. //音频格式转换
  18. ext := path.Ext(convAudioPath)
  19. inputFileStrList := strings.Split(convAudioPath, ext)
  20. if ext != ".mp3" {
  21. // 转换音频格式后的文件名
  22. convAudioPath = inputFileStrList[0] + "_conv.mp3"
  23. err = ConvertAudioFormat(inputFile, convAudioPath)
  24. if err != nil {
  25. //fmt.Println("ConvertAudioFormat Err:" + err.Error())
  26. return
  27. }
  28. // 退出后需要删除该临时文件
  29. defer func() {
  30. os.Remove(convAudioPath)
  31. }()
  32. }
  33. baseDecibels := -22.8 //基准音量分贝,dB
  34. // 音频的实际分贝 音频的实际分贝与基准分贝的差值
  35. var volumeFloat, diffDecibels float64
  36. //音频声音处理
  37. {
  38. tmpVolumeFloat, ok, tmpErr := extractVolume(convAudioPath)
  39. if tmpErr != nil {
  40. err = tmpErr
  41. return
  42. }
  43. if !ok {
  44. return
  45. }
  46. volumeFloat = tmpVolumeFloat
  47. // 分贝差值
  48. diffDecibels = volumeFloat - baseDecibels
  49. // 分贝差值在5dB误差内,那就不转了
  50. if math.Abs(diffDecibels) <= 5 {
  51. //fmt.Println("音频分贝在误差范围内,无需转音频")
  52. return
  53. }
  54. }
  55. //fmt.Println("开始转变音频分贝")
  56. // 分贝大小变更
  57. targetDecibels := "" // 目标分贝值
  58. //fmt.Println("分贝差值:", diffDecibels)
  59. if diffDecibels < 0 { // 原先的音频分贝过小,那么需要增大
  60. targetDecibels = fmt.Sprintf("+%sdB", utils.SubFloatToString(math.Abs(diffDecibels), 2))
  61. } else { // 原先的音频分贝过大,那么需要减小
  62. targetDecibels = fmt.Sprintf("-%sdB", utils.SubFloatToString(math.Abs(diffDecibels), 2))
  63. }
  64. //fmt.Println("开始转音频分贝:", targetDecibels)
  65. afCommandStr := "volume=" + targetDecibels
  66. //fmt.Println(afCommandStr)
  67. // 转换音频分贝格式后的文件名
  68. outputFile = inputFileStrList[0] + "_decibel.mp3"
  69. // 构建 FFmpeg 命令
  70. cmd := exec.Command("ffmpeg", "-y", "-i", convAudioPath, "-af", afCommandStr, outputFile)
  71. var out bytes.Buffer
  72. cmd.Stderr = &out
  73. // 执行 FFmpeg 命令
  74. err = cmd.Run()
  75. if err != nil {
  76. utils.FileLog.Info("转换音频分贝格式失败,FFmpeg命令返回:\n" + out.String())
  77. return
  78. }
  79. isConvDecibel = true
  80. //fmt.Println("音频文件的音量已设置成功!")
  81. return
  82. }
  83. // 从FFmpeg输出中提取音量信息
  84. func extractVolume(audioPath string) (decibels float64, ok bool, err error) {
  85. cmd := exec.Command("ffmpeg", "-i", audioPath, "-af", "volumedetect", "-f", "null", "-")
  86. var out bytes.Buffer
  87. cmd.Stderr = &out
  88. err = cmd.Run()
  89. if err != nil {
  90. return
  91. }
  92. output := out.String()
  93. //fmt.Println("output:", output)
  94. var volumeLine string
  95. lines := strings.Split(output, "\n")
  96. for _, line := range lines {
  97. if strings.Contains(line, "mean_volume:") {
  98. volumeLine = line
  99. break
  100. }
  101. }
  102. if volumeLine == `` {
  103. return
  104. }
  105. volumeArr := strings.Split(volumeLine, " ")
  106. if len(volumeArr) < 4 {
  107. return
  108. }
  109. //fmt.Println("volume start")
  110. //fmt.Println(volumeStr)
  111. //fmt.Println(volumeArr)
  112. //fmt.Println(len(volumeArr))
  113. //for k, v := range volumeArr {
  114. // fmt.Println(k, v)
  115. //}
  116. //fmt.Println("volume end")
  117. volume := volumeArr[4]
  118. decibels, err = convertToFloat(volume)
  119. ok = true
  120. //fmt.Println(audioPath, "音量分贝值为:", decibels)
  121. return
  122. }
  123. // 将字符串转换为浮点数
  124. func convertToFloat(str string) (float64, error) {
  125. str = strings.TrimSpace(str)
  126. value, err := strconv.ParseFloat(str, 64)
  127. if err != nil {
  128. return 0, err
  129. }
  130. return value, nil
  131. }
  132. // ConvertAudioFormat 转换音频文件格式
  133. func ConvertAudioFormat(inputFilePath, outputFilePath string) (err error) {
  134. cmd := exec.Command("ffmpeg", "-y", "-i", inputFilePath, "-codec:a", "libmp3lame", outputFilePath)
  135. err = cmd.Run()
  136. if err != nil {
  137. return
  138. }
  139. return nil
  140. }