file.go 4.2 KB

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