|
|
@@ -249,13 +249,38 @@ func SaveTmpFile(filename string, data io.Reader) (string, error) {
|
|
|
}
|
|
|
|
|
|
// GetAudioDuration returns the duration of an audio file in seconds.
|
|
|
-func GetAudioDuration(ctx context.Context, filename string) (float64, error) {
|
|
|
+func GetAudioDuration(ctx context.Context, filename string, ext string) (float64, error) {
|
|
|
// ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 {{input}}
|
|
|
c := exec.CommandContext(ctx, "ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", filename)
|
|
|
output, err := c.Output()
|
|
|
if err != nil {
|
|
|
return 0, errors.Wrap(err, "failed to get audio duration")
|
|
|
}
|
|
|
-
|
|
|
- return strconv.ParseFloat(string(bytes.TrimSpace(output)), 64)
|
|
|
+ durationStr := string(bytes.TrimSpace(output))
|
|
|
+ if durationStr == "N/A" {
|
|
|
+ // Create a temporary output file name
|
|
|
+ tmpFp, err := os.CreateTemp("", "audio-*"+ext)
|
|
|
+ if err != nil {
|
|
|
+ return 0, errors.Wrap(err, "failed to create temporary file")
|
|
|
+ }
|
|
|
+ tmpName := tmpFp.Name()
|
|
|
+ // Close immediately so ffmpeg can open the file on Windows.
|
|
|
+ _ = tmpFp.Close()
|
|
|
+ defer os.Remove(tmpName)
|
|
|
+
|
|
|
+ // ffmpeg -y -i filename -vcodec copy -acodec copy <tmpName>
|
|
|
+ ffmpegCmd := exec.CommandContext(ctx, "ffmpeg", "-y", "-i", filename, "-vcodec", "copy", "-acodec", "copy", tmpName)
|
|
|
+ if err := ffmpegCmd.Run(); err != nil {
|
|
|
+ return 0, errors.Wrap(err, "failed to run ffmpeg")
|
|
|
+ }
|
|
|
+
|
|
|
+ // Recalculate the duration of the new file
|
|
|
+ c = exec.CommandContext(ctx, "ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", tmpName)
|
|
|
+ output, err := c.Output()
|
|
|
+ if err != nil {
|
|
|
+ return 0, errors.Wrap(err, "failed to get audio duration after ffmpeg")
|
|
|
+ }
|
|
|
+ durationStr = string(bytes.TrimSpace(output))
|
|
|
+ }
|
|
|
+ return strconv.ParseFloat(durationStr, 64)
|
|
|
}
|