Source code for veditor.utils.audio_utils
# coding: utf-8
import logging
import os
import subprocess
from typing import List, Optional
from pydub import AudioSegment
from ._colorings import toBLUE
from .generic_utils import openf
[docs]def synthesize_audio(
video_path: str,
audio_path: str,
out_path: Optional[str] = None,
start: int = 0,
end: int = -1,
volume: int = 0,
offset: str = "00:00:00",
open: bool = True,
delete_intermidiates: bool = False,
logger: Optional[logging.Logger] = None,
) -> str:
"""Use ``ffmpeg`` directly or ``moviepy`` to synthesize audio (at ``audio_path``) to video (at ``video_path``)
Args:
video_path (str) : The path to video fiile.
audio_path (str) : The path to audio (video) fiile.
out_path (Optional[str], optional) : The path to the created video (with audio) file. Defaults to ``None``.
offset (str, optional) : Offset until the voice starts. Defaults to ``"00:00:00"``.
open (bool, optional) : Whether to open the created video or not. Defaults to ``True``.
delete_silence (bool, optional) : Whether to delete the silence video (``video_path``) or not. Defaults to ``False``.
Returns:
str: The path to the created video (with audio) file.
Examples:
>>> from veditor.utils import synthesize_audio
>>> # Prepare Audio file (.mp3)
>>> synthesize_audio(audio_path="sound.mp3", video_path="no_sound.mp4")
>>> # Prepare Video with Audio file (.mp4)
>>> synthesize_audio(audio_path="sound.mp4", video_path="no_sound.mp4")
"""
root, ext = os.path.splitext(audio_path)
intermediate_files: List[str] = []
if ext not in [".mp3", ".wav"]:
audio = AudioSegment.from_file(file=audio_path, format=ext[1:])
ext = ".mp3"
audio_path = root + ext
audio.export(out_f=root + ext, format=ext[1:])
intermediate_files.append(audio_path)
if start != 0 or end != -1:
audio = AudioSegment.from_file(file=audio_path, format=ext[1:])
audio_path = f"{root}_{start}-{end}-{volume}{ext}"
(audio[start:end] + volume).export(out_f=audio_path, format="mp3")
intermediate_files.append(audio_path)
if out_path is None:
out_path = f"_synthesized".join(os.path.splitext(video_path))
# Append Audio.
command = f"ffmpeg -y -itsoffset {offset} -i '{video_path}' -i '{audio_path}' -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 '{out_path}' -async 1 -strict -2"
if logger is not None:
logger.info(f"Run the following command:\n{command}")
subprocess.call(command, shell=True)
# Open the created video.
if open:
openf(out_path)
# Delete the silence video.
if delete_intermidiates:
for fp in intermediate_files:
os.remove(fp)
return out_path
[docs]def overlay_audio(
base_media_path: str,
overlay_media_path: str,
out_path: Optional[str] = None,
position: int = 0,
) -> str:
"""Overlay audio at ``overlay_media_path`` on audio at ``base_media_path``.
Args:
base_media_path (str) : The path to media file (contains audio) to be overlayed.
overlay_media_path (str) : The path to media file (contains audio) to overlay.
out_path (Optional[str], optional) : Path to the created audio file. Defaults to ``None``.
position (int, optional) : The position (``[ms]``) to start overlaying the provided segment in to this one. Defaults to ``0``.
Returns:
str: Path to the created audio file.
"""
root, ext = os.path.splitext(base_media_path)
base_audio = AudioSegment.from_file(file=base_media_path, format=ext[1:])
overlay_audio = AudioSegment.from_file(file=overlay_media_path)
if out_path is None:
out_path = f"{root}_overlayed.mp3"
base_audio.overlay(overlay_audio, position=int(position)).export(out_path)
return out_path