package audio import ( "bytes" "eta/eta_pub/utils" "fmt" "math" "os" "os/exec" "path" "strconv" "strings" ) // ConvAudioDecibel 音频分贝转换(生成新的文件) func ConvAudioDecibel(inputFile string) (outputFile string, isConvDecibel bool, err error) { // 转换音频格式后的音频地址 convAudioPath := inputFile //音频格式转换 ext := path.Ext(convAudioPath) inputFileStrList := strings.Split(convAudioPath, ext) if ext != ".mp3" { // 转换音频格式后的文件名 convAudioPath = inputFileStrList[0] + "_conv.mp3" err = ConvertAudioFormat(inputFile, convAudioPath) if err != nil { //fmt.Println("ConvertAudioFormat Err:" + err.Error()) return } // 退出后需要删除该临时文件 defer func() { os.Remove(convAudioPath) }() } baseDecibels := -22.8 //基准音量分贝,dB // 音频的实际分贝 音频的实际分贝与基准分贝的差值 var volumeFloat, diffDecibels float64 //音频声音处理 { tmpVolumeFloat, ok, tmpErr := extractVolume(convAudioPath) if tmpErr != nil { err = tmpErr return } if !ok { return } volumeFloat = tmpVolumeFloat // 分贝差值 diffDecibels = volumeFloat - baseDecibels // 分贝差值在5dB误差内,那就不转了 if math.Abs(diffDecibels) <= 5 { //fmt.Println("音频分贝在误差范围内,无需转音频") return } } //fmt.Println("开始转变音频分贝") // 分贝大小变更 targetDecibels := "" // 目标分贝值 //fmt.Println("分贝差值:", diffDecibels) if diffDecibels < 0 { // 原先的音频分贝过小,那么需要增大 targetDecibels = fmt.Sprintf("+%sdB", utils.SubFloatToString(math.Abs(diffDecibels), 2)) } else { // 原先的音频分贝过大,那么需要减小 targetDecibels = fmt.Sprintf("-%sdB", utils.SubFloatToString(math.Abs(diffDecibels), 2)) } //fmt.Println("开始转音频分贝:", targetDecibels) afCommandStr := "volume=" + targetDecibels //fmt.Println(afCommandStr) // 转换音频分贝格式后的文件名 outputFile = inputFileStrList[0] + "_decibel.mp3" // 构建 FFmpeg 命令 cmd := exec.Command("ffmpeg", "-y", "-i", convAudioPath, "-af", afCommandStr, outputFile) var out bytes.Buffer cmd.Stderr = &out // 执行 FFmpeg 命令 err = cmd.Run() if err != nil { utils.FileLog.Info("转换音频分贝格式失败,FFmpeg命令返回:\n" + out.String()) return } isConvDecibel = true //fmt.Println("音频文件的音量已设置成功!") return } // 从FFmpeg输出中提取音量信息 func extractVolume(audioPath string) (decibels float64, ok bool, err error) { cmd := exec.Command("ffmpeg", "-i", audioPath, "-af", "volumedetect", "-f", "null", "-") var out bytes.Buffer cmd.Stderr = &out err = cmd.Run() if err != nil { return } output := out.String() //fmt.Println("output:", output) var volumeLine string lines := strings.Split(output, "\n") for _, line := range lines { if strings.Contains(line, "mean_volume:") { volumeLine = line break } } if volumeLine == `` { return } volumeArr := strings.Split(volumeLine, " ") if len(volumeArr) < 4 { return } //fmt.Println("volume start") //fmt.Println(volumeStr) //fmt.Println(volumeArr) //fmt.Println(len(volumeArr)) //for k, v := range volumeArr { // fmt.Println(k, v) //} //fmt.Println("volume end") volume := volumeArr[4] decibels, err = convertToFloat(volume) ok = true //fmt.Println(audioPath, "音量分贝值为:", decibels) return } // 将字符串转换为浮点数 func convertToFloat(str string) (float64, error) { str = strings.TrimSpace(str) value, err := strconv.ParseFloat(str, 64) if err != nil { return 0, err } return value, nil } // ConvertAudioFormat 转换音频文件格式 func ConvertAudioFormat(inputFilePath, outputFilePath string) (err error) { cmd := exec.Command("ffmpeg", "-y", "-i", inputFilePath, "-codec:a", "libmp3lame", outputFilePath) err = cmd.Run() if err != nil { return } return nil }