93 lines
2.5 KiB
Go
93 lines
2.5 KiB
Go
package helpers
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"os/exec"
|
||
"path/filepath"
|
||
"strings"
|
||
)
|
||
|
||
// ConvertToOpusOggTemp – creates a temporary .ogg file in Opus format
|
||
// Uses reasonable defaults for WhatsApp voice messages
|
||
func ConvertToOpusOggTemp(inputFile string) (string, error) {
|
||
// WhatsApp voice messages usually use:
|
||
// bitrate → 24k–32k is very common and good quality/size balance
|
||
// sample rate → 48000 Hz (Opus native)
|
||
const defaultBitrate = "32k"
|
||
const defaultSampleRate = 48000
|
||
|
||
return ConvertToOpusOggTempWithParams(inputFile, defaultBitrate, defaultSampleRate)
|
||
}
|
||
|
||
// ConvertToOpusOgg converts an audio file to Opus format in an Ogg container.
|
||
func ConvertToOpusOgg(inputFile string, outputFile string, bitrate string, sampleRate int) (string, error) {
|
||
// Check if input file exists
|
||
if _, err := os.Stat(inputFile); os.IsNotExist(err) {
|
||
return "", fmt.Errorf("input file not found: %s", inputFile)
|
||
}
|
||
|
||
// If no output file is specified, replace extension with .ogg
|
||
if outputFile == "" {
|
||
ext := filepath.Ext(inputFile)
|
||
outputFile = strings.TrimSuffix(inputFile, ext) + ".ogg"
|
||
}
|
||
|
||
// Ensure output directory exists
|
||
outputDir := filepath.Dir(outputFile)
|
||
if outputDir != "." {
|
||
if err := os.MkdirAll(outputDir, 0755); err != nil {
|
||
return "", fmt.Errorf("failed to create output directory: %w", err)
|
||
}
|
||
}
|
||
|
||
// Build the ffmpeg command
|
||
cmd := exec.Command("ffmpeg",
|
||
"-i", inputFile,
|
||
"-c:a", "libopus",
|
||
"-b:a", bitrate,
|
||
"-ar", fmt.Sprintf("%d", sampleRate),
|
||
"-application", "voip",
|
||
"-vbr", "on",
|
||
"-compression_level", "10",
|
||
"-frame_duration", "60",
|
||
"-y",
|
||
outputFile,
|
||
)
|
||
|
||
// Run command and capture output for error reporting
|
||
output, err := cmd.CombinedOutput()
|
||
if err != nil {
|
||
return "", fmt.Errorf("failed to convert audio. ffmpeg error: %s (%w)", string(output), err)
|
||
}
|
||
|
||
return outputFile, nil
|
||
}
|
||
|
||
// ConvertToOpusOggTempWithParams converts audio to a temporary .ogg file.
|
||
func ConvertToOpusOggTempWithParams(inputFile string, bitrate string, sampleRate int) (string, error) {
|
||
// Create a temporary file
|
||
tempFile, err := os.CreateTemp("", "audio-*.ogg")
|
||
if err != nil {
|
||
return "", fmt.Errorf("failed to create temp file: %w", err)
|
||
}
|
||
tempPath := tempFile.Name()
|
||
err = tempFile.Close()
|
||
if err != nil {
|
||
return "", err
|
||
} // Close it so ffmpeg can write to the path
|
||
|
||
// Convert the audio
|
||
result, err := ConvertToOpusOgg(inputFile, tempPath, bitrate, sampleRate)
|
||
if err != nil {
|
||
// Clean up on failure
|
||
err := os.Remove(tempPath)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return "", err
|
||
}
|
||
|
||
return result, nil
|
||
}
|