file.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. package utils
  2. import (
  3. "encoding/base64"
  4. "fmt"
  5. "io"
  6. "log"
  7. "os"
  8. "os/exec"
  9. "path/filepath"
  10. "pbx-api-gin/internal/pkg/configs"
  11. "pbx-api-gin/pkg/lfshook"
  12. "strconv"
  13. "strings"
  14. )
  15. // FileExists checks if a file exists and is not a directory before we
  16. // try using it to prevent further errors.
  17. func FileExists(filename string) bool {
  18. info, err := os.Stat(filename)
  19. if os.IsNotExist(err) {
  20. return false
  21. }
  22. return !info.IsDir()
  23. }
  24. func GetDuration(filePath string) (int, error) {
  25. cmd := exec.Command("ffprobe",
  26. "-v", "quiet",
  27. "-show_entries", "format=duration",
  28. "-of", "default=nw=1:nokey=1",
  29. filePath,
  30. )
  31. output, err := cmd.Output()
  32. if err != nil {
  33. return 0, err
  34. }
  35. // 解析输出(纯数字,单位秒)
  36. durationStr := strings.TrimSpace(string(output))
  37. duration, err := strconv.ParseFloat(durationStr, 64)
  38. if err != nil {
  39. return 0, err
  40. }
  41. return int(duration), nil
  42. }
  43. func AudioFileEncode(dstFile, srcFile string) error {
  44. data := "sripis123"
  45. encoded := base64.StdEncoding.EncodeToString([]byte(data))
  46. // Step 2: 创建一个新文件,写入 Base64 编码结果
  47. outputFile, err := os.Create(dstFile)
  48. if err != nil {
  49. return err
  50. }
  51. defer outputFile.Close()
  52. _, err = outputFile.WriteString(encoded)
  53. if err != nil {
  54. return err
  55. }
  56. // Step 3: 打开 audio.wav 文件
  57. audioFile, err := os.Open(srcFile)
  58. if err != nil {
  59. return err
  60. }
  61. defer audioFile.Close()
  62. // Step 4: 将 audio.wav 的内容追加到 output.bin 文件末尾
  63. _, err = audioFile.Seek(0, io.SeekStart) // 确保从文件开头读取
  64. if err != nil {
  65. return err
  66. }
  67. _, err = io.Copy(outputFile, audioFile)
  68. if err != nil {
  69. return err
  70. }
  71. return err
  72. }
  73. // ConvertAndSegmentWAV 将 WAV 文件转为 22kHz 并每 180 秒切分,返回生成的文件名列表
  74. func ConvertAndSegmentWAV(inputFile string, outputPrefix string) ([]string, error) {
  75. // 输出文件命名模式,如:output_%03d.wav
  76. outputPattern := outputPrefix + "_%03d.wav"
  77. // 构建 ffmpeg 命令
  78. cmd := exec.Command("ffmpeg",
  79. "-i", inputFile, // 输入文件
  80. "-ar", "22050", // 设置采样率为 22050 Hz (22kHz)
  81. "-f", "segment", // 启用分段模式
  82. "-segment_time", "180", // 每段 180 秒
  83. "-c:a", "pcm_s16le", // 音频编码格式(标准 WAV)
  84. "-reset_timestamps", "1", // 重置时间戳,每个片段从 0 开始
  85. outputPattern, // 输出文件命名规则
  86. )
  87. // 执行命令并捕获输出
  88. output, err := cmd.CombinedOutput()
  89. if err != nil && !strings.Contains(string(output), "Conversion failed!") {
  90. // 即使有警告(如非关键错误),只要文件生成了就继续解析
  91. log.Printf("ffmpeg 执行时有警告: %v", err)
  92. }
  93. // 解析输出,提取所有生成的文件名
  94. files := extractFilenamesFromFFmpegOutput(outputPrefix)
  95. lfshook.NewLogger().Infof("=============== found after convert outfiles %+v ", files)
  96. return files, nil
  97. }
  98. // extractFilenamesFromFFmpegOutput 从 ffmpeg 输出日志中提取生成的文件名
  99. func extractFilenamesFromFFmpegOutput(prefix string) []string {
  100. pattern := fmt.Sprintf("%s_*", prefix)
  101. matches, err := filepath.Glob(pattern)
  102. if err != nil {
  103. log.Fatal("模式匹配错误:", err)
  104. }
  105. return matches
  106. }
  107. func WriteLogToFile(message string) {
  108. // 打开文件,支持追加模式,如果文件不存在则创建
  109. file, err := os.OpenFile(configs.ConfigGlobal.RecordEventLog, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  110. if err != nil {
  111. return
  112. }
  113. defer file.Close()
  114. // 创建一个写入到文件的日志器
  115. logger := log.New(file, "", log.LstdFlags)
  116. // 写入日志消息
  117. logger.Println(message)
  118. }
  119. var Logger *log.Logger
  120. func init() {
  121. file, _ := os.OpenFile("/data/test/log/recordEvent.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
  122. Logger = log.New(file, "", log.LstdFlags) // 自动带时间戳
  123. }
  124. func GetPadInfo(base string) (padType, padNum, connectedCab string) {
  125. // 按 '/' 分割字符串
  126. parts := strings.Split(base, "/")
  127. // 取最后一段
  128. lastPart := parts[len(parts)-1]
  129. // 最后一段中,按‘-’分割返回前三段:parts[0], parts[1], parts[2] → PAD-2411-1411
  130. ret := strings.Split(lastPart, "-")
  131. if len(ret) < 3 {
  132. return
  133. }
  134. return ret[1], ret[2], ret[3]
  135. }