From 4aa262cbfe008858d07070ca3e46ea50f8a9d697 Mon Sep 17 00:00:00 2001 From: miro Date: Wed, 19 Jun 2024 18:20:37 +0100 Subject: [PATCH] new_util/get_sound_duration --- ovos_utils/sound.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/ovos_utils/sound.py b/ovos_utils/sound.py index d211b4d6..efe51ff7 100644 --- a/ovos_utils/sound.py +++ b/ovos_utils/sound.py @@ -1,6 +1,10 @@ import os import subprocess +import wave from copy import deepcopy +from os.path import isfile +from typing import Optional + from distutils.spawn import find_executable from ovos_utils.log import LOG @@ -115,3 +119,36 @@ def play_audio(uri, play_cmd=None, environment=None): LOG.error(f"Failed to play: {play_cmd}") LOG.exception(e) return None + + +def get_sound_duration(path: str, base_dir: Optional[str] = "") -> float: + """return sound duration, in seconds""" + if base_dir and path.startswith("snd/"): + resolved_path = f"{base_dir}/{path}" + if isfile(resolved_path): + path = resolved_path + + if not isfile(path): + raise FileNotFoundError(f"could not resolve sound file: {path}") + + if path.endswith(".wav"): + with wave.open(path, 'r') as f: + frames = f.getnframes() + rate = f.getframerate() + return frames / float(rate) + media_info = find_executable("mediainfo") + if media_info: + args = (media_info, path) + popen = subprocess.Popen(args, stdout=subprocess.PIPE) + popen.wait() + output = popen.stdout.read().decode("utf-8").split("Duration")[1].split("\n")[0] + output = "".join([c for c in output if c.isdigit()]) + return int(output) / 1000 + ffprobe = find_executable("ffprobe") + if ffprobe: + args = (ffprobe, "-show_entries", "format=duration", "-i", path) + popen = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + popen.wait() + output = popen.stdout.read().decode("utf-8") + return float(output.split("duration=")[-1].split("\n")[0]) + raise RuntimeError("Failed to determine sound length, please install mediainfo or ffprobe")