single iteration working
This commit is contained in:
0
src/__init__.py
Normal file
0
src/__init__.py
Normal file
0
src/editors/__init__.py
Normal file
0
src/editors/__init__.py
Normal file
0
src/editors/amplitude/__init__.py
Normal file
0
src/editors/amplitude/__init__.py
Normal file
29
src/editors/amplitude/editor.py
Normal file
29
src/editors/amplitude/editor.py
Normal file
@ -0,0 +1,29 @@
|
||||
from ...mediautils.audio import process_audio, resample
|
||||
from ...math.average import np_moving_average
|
||||
from ...models.moment import Moment
|
||||
from ..common import find_moving_average_highlights
|
||||
import numpy as np
|
||||
import structlog
|
||||
|
||||
class AmplitudeEditor:
|
||||
def __init__(self, video_path, audio_path, params):
|
||||
self.logger = structlog.get_logger("amplitude")
|
||||
self.video_path = video_path
|
||||
self.audio_path = audio_path
|
||||
self.logger.info("processing audio", path=self.audio_path)
|
||||
data, duration, bitrate = process_audio(self.audio_path)
|
||||
self.data = data
|
||||
self.duration = duration
|
||||
self.bitrate = bitrate
|
||||
self.factor = params["factor"]
|
||||
self.logger.info("resampling audio", factor=self.factor)
|
||||
self.subsampled_data = resample(self.data, self.factor)
|
||||
self.squared_subsample = np.square(self.subsampled_data)
|
||||
|
||||
def edit(self, large_window, small_window, params):
|
||||
window_factor = self.bitrate / self.factor
|
||||
long_ma = np_moving_average(self.squared_subsample, large_window * window_factor)
|
||||
short_ma = np_moving_average(self.squared_subsample, small_window * window_factor)
|
||||
highlights = find_moving_average_highlights(short_ma, long_ma, self.factor / self.bitrate)
|
||||
return highlights
|
||||
|
25
src/editors/common.py
Normal file
25
src/editors/common.py
Normal file
@ -0,0 +1,25 @@
|
||||
from ..models.moment import Moment
|
||||
|
||||
def find_moving_average_highlights(short_ma, long_ma, scaling_factor=1):
|
||||
in_a_clip = False
|
||||
m = None
|
||||
ret_list = []
|
||||
for t in range(1, len(long_ma)):
|
||||
if (
|
||||
not in_a_clip
|
||||
and (short_ma[t - 1] < long_ma[t - 1])
|
||||
and (short_ma[t] > long_ma[t])
|
||||
):
|
||||
in_a_clip = True
|
||||
m = Moment(t * scaling_factor, 0)
|
||||
elif (
|
||||
in_a_clip
|
||||
and (short_ma[t - 1] > long_ma[t - 1])
|
||||
and (short_ma[t] < long_ma[t])
|
||||
):
|
||||
in_a_clip = False
|
||||
m.stop = t * scaling_factor
|
||||
ret_list.append(m)
|
||||
m = None
|
||||
|
||||
return ret_list
|
0
src/editors/sentiment/__init__.py
Normal file
0
src/editors/sentiment/__init__.py
Normal file
3
src/editors/sentiment/editor.py
Normal file
3
src/editors/sentiment/editor.py
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
class SentimentEditor:
|
||||
pass
|
0
src/math/__init__.py
Normal file
0
src/math/__init__.py
Normal file
4
src/math/average.py
Normal file
4
src/math/average.py
Normal file
@ -0,0 +1,4 @@
|
||||
import numpy as np
|
||||
|
||||
def np_moving_average(data: int, window: int) -> np.ndarray:
|
||||
return np.convolve(data, np.ones(int(window)), "valid") / window
|
8
src/math/distribution.py
Normal file
8
src/math/distribution.py
Normal file
@ -0,0 +1,8 @@
|
||||
import numpy as np
|
||||
|
||||
def create_distribution(center, spread, count):
|
||||
high = center * (1.0 + spread)
|
||||
low = center - (center * spread)
|
||||
if low < 0:
|
||||
low = 0
|
||||
return np.random.uniform(low, high, count)
|
0
src/mediautils/__init__.py
Normal file
0
src/mediautils/__init__.py
Normal file
30
src/mediautils/audio.py
Normal file
30
src/mediautils/audio.py
Normal file
@ -0,0 +1,30 @@
|
||||
import tempfile
|
||||
import moviepy.editor as mp
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
import scipy.io.wavfile as wav
|
||||
|
||||
def extract_audio_from_video(
|
||||
video_path: str,
|
||||
filename: str
|
||||
):
|
||||
tempdir = tempfile.gettempdir()
|
||||
|
||||
dest_location = f"{tempdir}/{filename}.wav"
|
||||
if Path(dest_location).is_file():
|
||||
return dest_location, True
|
||||
|
||||
vid = mp.VideoFileClip(video_path)
|
||||
vid.audio.write_audiofile(dest_location, logger=None)
|
||||
vid.close()
|
||||
return dest_location, False
|
||||
|
||||
def process_audio(source_audio_path):
|
||||
rate, data_raw = wav.read(source_audio_path)
|
||||
data_raw = data_raw.astype(np.int32)
|
||||
mono = (data_raw[:, 0] + data_raw[:, 1]) / 2
|
||||
duration = len(mono) / rate
|
||||
return mono, duration, rate
|
||||
|
||||
def resample(data: np.ndarray, factor: int) -> np.ndarray:
|
||||
return data[::factor].copy()
|
0
src/models/__init__.py
Normal file
0
src/models/__init__.py
Normal file
9
src/models/moment.py
Normal file
9
src/models/moment.py
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
class Moment:
|
||||
|
||||
def __init__(self, start, stop):
|
||||
self.start = start
|
||||
self.stop = stop
|
||||
|
||||
def get_duration(self):
|
||||
return self.stop - self.start
|
Reference in New Issue
Block a user