Skip to content

Commit

Permalink
Merge branch 'main' into philip/improve_error_handling
Browse files Browse the repository at this point in the history
  • Loading branch information
philipqueen authored Aug 26, 2024
2 parents d3aaa38 + da8b147 commit ecb9e22
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 46 deletions.
4 changes: 3 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[flake8]

per-file-ignores = ./skelly_synchronize/tests/*:S101
per-file-ignores =
./skelly_synchronize/tests/*:S101
./skelly_synchronize/__init__.py:F401

max-line-length = 88

Expand Down
8 changes: 5 additions & 3 deletions skelly_synchronize/core_processes/audio_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from skelly_synchronize.system.file_extensions import AudioExtension
from skelly_synchronize.system.paths_and_file_names import TRIMMED_AUDIO_FOLDER_NAME

logger = logging.getLogger(__name__)


def get_audio_sample_rates(video_info_dict: Dict[str, dict]) -> list:
"""Get the sample rates of each audio file and return them in a list"""
Expand Down Expand Up @@ -49,7 +51,7 @@ def extract_audio_files(
audio_signal, sample_rate = librosa.load(path=audio_file_path, sr=None)

audio_duration = librosa.get_duration(y=audio_signal, sr=sample_rate)
logging.info(f"audio file {audio_name} is {audio_duration} seconds long")
logger.info(f"audio file {audio_name} is {audio_duration} seconds long")
audio_signal_dict[audio_name] = {
"audio file": audio_signal,
"sample rate": sample_rate,
Expand All @@ -63,7 +65,7 @@ def extract_audio_files(
def trim_audio_files(
audio_folder_path: Path, lag_dictionary: dict, synced_video_length: float, audio_extension: AudioExtension = AudioExtension.WAV
):
logging.info("Trimming audio files to match synchronized video length")
logger.info("Trimming audio files to match synchronized video length")

trimmed_audio_folder_path = Path(audio_folder_path) / TRIMMED_AUDIO_FOLDER_NAME
trimmed_audio_folder_path.mkdir(parents=True, exist_ok=True)
Expand All @@ -82,7 +84,7 @@ def trim_audio_files(

audio_filename = f"{audio_filepath.stem}.{AudioExtension.WAV.value}"

logging.info(f"Saving audio {audio_filename}")
logger.info(f"Saving audio {audio_filename}")
output_path = trimmed_audio_folder_path / audio_filename
sf.write(output_path, shortened_audio_signal, sr, subtype="PCM_24")

Expand Down
12 changes: 7 additions & 5 deletions skelly_synchronize/core_processes/correlation_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from skelly_synchronize.system.file_extensions import NUMPY_EXTENSION
from skelly_synchronize.system.paths_and_file_names import BRIGHTNESS_SUFFIX

logger = logging.getLogger(__name__)


def cross_correlate(audio1: np.ndarray, audio2: np.ndarray):
"""Take two audio files, synchronize them using cross correlation, and trim them to the same length.
Expand All @@ -28,7 +30,7 @@ def cross_correlate(audio1: np.ndarray, audio2: np.ndarray):
def find_first_brightness_change(
video_pathstring: str, brightness_ratio_threshold: float = 1000
) -> int:
logging.info(f"Detecting first brightness change in {video_pathstring}")
logger.info(f"Detecting first brightness change in {video_pathstring}")
brightness_array = find_brightness_across_frames(video_pathstring)
brightness_difference = np.diff(brightness_array, prepend=brightness_array[0])
brightness_double_difference = np.diff(
Expand All @@ -42,12 +44,12 @@ def find_first_brightness_change(
)

if first_brightness_change == 0:
logging.info(
logger.info(
"No brightness change exceeded threshold, defaulting to frame with fastest detected brightness change"
)
first_brightness_change = np.argmax(brightness_double_difference)
else:
logging.info(
logger.info(
f"First brightness change detected at frame number {first_brightness_change}"
)

Expand Down Expand Up @@ -95,7 +97,7 @@ def find_cross_correlation_lags(
The lag dict is normalized so that the lag of the latest video to start in time is 0, and all other lags are positive.
"""
comparison_file_key = next(iter(audio_signal_dict))
logging.info(
logger.info(
f"comparison file is: {comparison_file_key}, sample rate is: {sample_rate}"
)

Expand All @@ -110,7 +112,7 @@ def find_cross_correlation_lags(

normalized_lag_dict = normalize_lag_dictionary(lag_dictionary=lag_dict)

logging.info(
logger.info(
f"original lag dict: {lag_dict} normalized lag dict: {normalized_lag_dict}"
)

Expand Down
10 changes: 6 additions & 4 deletions skelly_synchronize/core_processes/debugging/debug_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
TRIMMED_AUDIO_FOLDER_NAME,
)

logger = logging.getLogger(__name__)


def create_brightness_debug_plots(
raw_video_folder_path: Path, synchronized_video_folder_path: Path
Expand All @@ -26,7 +28,7 @@ def create_brightness_debug_plots(
folder_path=synchronized_video_folder_path
)

logging.info("Creating debug plots")
logger.info("Creating debug plots")
plot_brightness_across_frames(
raw_brightness_npys=list_of_raw_brightness_paths,
trimmed_brightness_npys=list_of_trimmed_brightness_paths,
Expand All @@ -42,7 +44,7 @@ def create_audio_debug_plots(synchronized_video_folder_path: Path):
list_of_raw_audio_paths = get_audio_paths_from_folder(raw_audio_folder_path)
list_of_trimmed_audio_paths = get_audio_paths_from_folder(trimmed_audio_folder_path)

logging.info("Creating debug plots")
logger.info("Creating debug plots")
plot_audio_waveforms(
raw_audio_filepath_list=list_of_raw_audio_paths,
trimmed_audio_filepath_list=list_of_trimmed_audio_paths,
Expand Down Expand Up @@ -91,7 +93,7 @@ def plot_brightness_across_frames(

axs[1].plot(time, brightness_array, alpha=0.5)

logging.info(f"Saving debug plots to: {output_filepath}")
logger.info(f"Saving debug plots to: {output_filepath}")
plt.savefig(output_filepath)


Expand Down Expand Up @@ -124,5 +126,5 @@ def plot_audio_waveforms(

axs[1].plot(time, audio_signal, alpha=0.4)

logging.info(f"Saving debug plots to: {output_filepath}")
logger.info(f"Saving debug plots to: {output_filepath}")
plt.savefig(output_filepath)
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
check_if_video_has_reversed_metadata,
)

logger = logging.getLogger(__name__)


def trim_single_video_deffcode(
input_video_pathstring: str,
Expand All @@ -18,7 +20,7 @@ def trim_single_video_deffcode(
)

if vertical_video_bool:
logging.info("Video has reversed metadata, changing FFmpeg transpose argument")
logger.info("Video has reversed metadata, changing FFmpeg transpose argument")
ffparams = {"-ffprefixes": ["-noautorotate"], "-vf": "transpose=1"}
else:
ffparams = {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,36 @@
import logging
import subprocess
import shutil
from pathlib import Path
from typing import Union

from skelly_synchronize.system.file_extensions import AudioExtension

logger = logging.getLogger(__name__)

ffmpeg_string = "ffmpeg"
ffprobe_string = "ffprobe"


def check_for_ffmpeg():
if shutil.which(ffmpeg_string) is None:
raise FileNotFoundError(
"ffmpeg not found, please install ffmpeg and add it to your PATH"
)


def check_for_ffprobe():
if shutil.which(ffprobe_string) is None:
raise FileNotFoundError(
"ffprobe not found, please install ffmpeg and add it to your PATH"
)


def extract_audio_from_video_ffmpeg(
file_pathstring: str, output_file_path: Union[Path, str]
):
"""Run a subprocess call to extract the audio from a video file using ffmpeg"""

check_for_ffmpeg()
if str(Path(output_file_path).suffix).strip(".") not in {
extension.value for extension in AudioExtension
}:
Expand All @@ -19,7 +40,7 @@ def extract_audio_from_video_ffmpeg(

extract_audio_subprocess = subprocess.run(
[
"ffmpeg",
ffmpeg_string,
"-y",
"-i",
file_pathstring,
Expand All @@ -38,9 +59,10 @@ def extract_audio_from_video_ffmpeg(
def extract_video_duration_ffmpeg(file_pathstring: str):
"""Run a subprocess call to get the duration from a video file using ffmpeg"""

check_for_ffprobe()
extract_duration_subprocess = subprocess.run(
[
"ffprobe",
ffprobe_string,
"-v",
"error",
"-show_entries",
Expand All @@ -66,9 +88,10 @@ def extract_video_duration_ffmpeg(file_pathstring: str):
def extract_video_fps_ffmpeg(file_pathstring: str):
"""Run a subprocess call to get the fps of a video file using ffmpeg"""

check_for_ffprobe()
extract_fps_subprocess = subprocess.run(
[
"ffprobe",
ffprobe_string,
"-v",
"error",
"-select_streams",
Expand Down Expand Up @@ -99,9 +122,10 @@ def extract_video_fps_ffmpeg(file_pathstring: str):
def extract_audio_sample_rate_ffmpeg(file_pathstring: str):
"""Run a subprocess call to get the audio sample rate of a video file using ffmpeg"""

check_for_ffprobe()
extract_sample_rate_subprocess = subprocess.run(
[
"ffprobe",
ffprobe_string,
"-v",
"error",
"-select_streams",
Expand Down Expand Up @@ -138,9 +162,10 @@ def normalize_framerates_in_video_ffmpeg(
):
"""Run a subprocess call to normalize the framerate and audio sample rate of a video file using ffmpeg"""

check_for_ffmpeg()
normalize_framerates_subprocess = subprocess.run(
[
"ffmpeg",
ffmpeg_string,
"-i",
f"{input_video_pathstring}",
"-r",
Expand All @@ -165,10 +190,10 @@ def trim_single_video_ffmpeg(
output_video_pathstring: str,
):
"""Run a subprocess call to trim a video from start time to last as long as the desired duration"""

check_for_ffmpeg()
trim_video_subprocess = subprocess.run(
[
"ffmpeg",
ffmpeg_string,
"-i",
f"{input_video_pathstring}",
"-ss",
Expand All @@ -195,9 +220,10 @@ def attach_audio_to_video_ffmpeg(
):
"""Run a subprocess call to attach audio file back to the video"""

check_for_ffmpeg()
attach_audio_subprocess = subprocess.run(
[
"ffmpeg",
ffmpeg_string,
"-i",
f"{input_video_pathstring}",
"-i",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
name_synced_video,
)

logger = logging.getLogger(__name__)


def create_video_info_dict(
video_filepath_list: list, video_handler: str = "ffmpeg"
Expand Down Expand Up @@ -61,7 +63,7 @@ def trim_videos(
minimum_frames = int(minimum_duration * fps)

for video_dict in video_info_dict.values():
logging.debug(f"trimming video file {video_dict['camera name']}")
logger.debug(f"trimming video file {video_dict['camera name']}")
synced_video_name = name_synced_video(
raw_video_filename=video_dict["camera name"]
)
Expand All @@ -73,8 +75,8 @@ def trim_videos(
)

if video_handler == "ffmpeg":
logging.info(f"Saving video - Cam name: {video_dict['camera name']}")
logging.info(f"desired saving duration is: {minimum_duration} seconds")
logger.info(f"Saving video - Cam name: {video_dict['camera name']}")
logger.info(f"desired saving duration is: {minimum_duration} seconds")
trim_single_video_ffmpeg(
input_video_pathstring=video_dict["video pathstring"],
start_time=start_time,
Expand All @@ -83,12 +85,12 @@ def trim_videos(
synchronized_folder_path / synced_video_name
),
)
logging.info(
logger.info(
f"Video Saved - Cam name: {video_dict['camera name']}, Video Duration in Seconds: {minimum_duration}"
)
if video_handler == "deffcode":
logging.info(f"Saving video - Cam name: {video_dict['camera name']}")
logging.info(
logger.info(f"Saving video - Cam name: {video_dict['camera name']}")
logger.info(
f"start frame is: {start_frame} desired saving duration is: {minimum_frames} frames"
)
trim_single_video_deffcode(
Expand All @@ -98,7 +100,7 @@ def trim_videos(
synchronized_folder_path / synced_video_name
),
)
logging.info(
logger.info(
f"Video Saved - Cam name: {video_dict['camera name']}, Video Duration in Frames: {minimum_frames}"
)

Expand Down Expand Up @@ -154,7 +156,7 @@ def attach_audio_to_videos(
/ f"{video_name}_with_audio_temp.{VideoExtension.MP4.value}"
)

logging.info(f"Attaching audio to video {video_name}")
logger.info(f"Attaching audio to video {video_name}")
attach_audio_to_video_ffmpeg(
input_video_pathstring=str(video),
audio_file_pathstring=str(
Expand Down
1 change: 0 additions & 1 deletion skelly_synchronize/gui/skelly_synchronize_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
QHBoxLayout,
)

from gui.widgets.run_button_widget import RunButtonWidget
from skelly_synchronize.skelly_synchronize import (
synchronize_videos_from_audio,
synchronize_videos_from_brightness,
Expand Down
Loading

0 comments on commit ecb9e22

Please sign in to comment.