\w+)')``
re_code = None
# Compilede regec (:py:func:`re.compile`) to detect, if input URL is valid for current backend.
# Example: ``re.compile(r'^http://myvideo\.com/.*')``
re_detect = None
# Pattern in which the code is inserted.
# Example: ``http://myvideo.com?code=%s``
# :type: str
pattern_url = None
pattern_thumbnail_url = None
re_detect = re.compile(
r'^(http(s)?://)?(www\.|m\.)?youtu(\.?)be(\.com)?/.*', re.I
)
re_code = re.compile(
r'''youtu(\.?)be(\.com)?/ # match youtube's domains
(\#/)? # for mobile urls
(embed/)? # match the embed url syntax
(v/)?
(watch\?v=)? # match the youtube page url
(ytscreeningroom\?v=)?
(feeds/api/videos/)?
(user\S*[^\w\-\s])?
(?P[\w\-]{11})[a-z0-9;:@?&%=+/\$_.-]* # match and extract
''',
re.I | re.X
)
pattern_url = '{protocol}://www.youtube.com/embed/{code}'
pattern_thumbnail_url = '{protocol}://img.youtube.com/vi/{code}/{resolution}'
resolutions = [
'maxresdefault.jpg',
'sddefault.jpg',
'hqdefault.jpg',
'mqdefault.jpg',
]
def get_url(self):
"""
Returns URL folded from :py:data:`pattern_url` and parsed code.
"""
url = self.pattern_url.format(code=self.code, protocol=self.protocol)
url += '?' + self.query.urlencode() if self.query else ''
return url
def get_thumbnail_url(self):
"""
Returns thumbnail URL folded from :py:data:`pattern_thumbnail_url` and
parsed code.
:rtype: str
"""
return self.pattern_thumbnail_url.format(code=self.code,
protocol=self.protocol)
def _getCode(self):
match = self.re_code.search(self._source_location)
if match:
return match.group('code')
parsed_url = urllib.parse.urlparse(self._source_location)
parsed_qs = urllib.parse.parse_qs(parsed_url.query)
if 'v' in parsed_qs:
code = parsed_qs['v'][0]
elif 'video_id' in parsed_qs:
code = parsed_qs['video_id'][0]
else:
raise UnknownIdException('Cannot get ID from `{0}`'.format(self._source_location))
return code
def get_thumbnail_url(self):
"""
Returns thumbnail URL folded from :py:data:`pattern_thumbnail_url` and
parsed code.
:rtype: str
"""
for resolution in self.resolutions:
temp_thumbnail_url = self.pattern_thumbnail_url.format(
code=self.code, protocol=self.protocol, resolution=resolution)
if int(requests.head(temp_thumbnail_url).status_code) < 400:
return temp_thumbnail_url
return None
class FilePathURL(SourceURL):
@classmethod
def SourceLocationType(cls):
return 'file_path';
def __init__(self, source_location):
self.source_location_type = self.SourceLocationType()
self._source_location = source_location;
@classmethod
def is_valid(cls, source_location):
return os.path.isfile(source_location);
def _getCode(self):
name_parts = os.path.splitext(os.path.basename(self._source_location));
return name_parts[0];
SOURCE_LOCATION_TYPES = (
YoutubeURL,
FilePathURL,
)
def ParseSourseLocation(url):
"""
:param url:
:return:
"""
for backend in SOURCE_LOCATION_TYPES:
if backend.is_valid(url):
return backend(url)
raise UnknownBackendException
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/TimeSignal.py
================================================
from .VBObject import *
from .Event import *
import math
from operator import truediv
from .VisBeatImports import *
class TimeSignal(VBObject):
"""TimeSignal (class): A time signal, and a bunch of convenience functions to go with it.
Attributes:
sampling_rate: the sampling rate
visualizations dictionary of visualizations. (removed - too many dependencies)
"""
def VBBJECT_TYPE(self):
return 'TimeSignal';
def __init__(self, path=None, sampling_rate = None):
VBObject.__init__(self, path=path);
# self.initializeBlank();
# self.visualizations = AFuncDict(owner=self, name='visualizations');
# self.visualizations.functions.update(self.VIS_FUNCS);
if(sampling_rate):
self.sampling_rate=sampling_rate;
def initializeBlank(self):
VBObject.initializeBlank(self);
self.sampling_rate = None;
#
@property
def frame_rate(self):
return self._getFrameRate();
def _getFrameRate(self):
raise NotImplementedError;
#
def getSampleAtTime(self, f):
prev_sample = self.getSampleAtIndex(math.floor(f));
next_sample = self.getSampleAtIndex(math.ceil(f));
sample_progress = f-np.floor(f);
return (next_sample*sample_progress)+(prev_sample*(1.0-sample_progress));
def getSampleAtIndex(self, i):
return self.getTimeForIndex();
def getDuration(self):
assert(False), "getDuration must be implemented for subclass of TimeSignal"
def getSampleDuration(self):
return 1.0/self.sampling_rate;
def getTimeForIndex(self, i):
return i*self.getSampleDuration();
# def toDictionary(self):
# d = VBObject.toDictionary(self);
# assert(False), "haven't implemented toDictionary for {} yet".format(self.VBOBJECT_TYPE())
# #serialize class specific members
# return d;
# def initFromDictionary(self, d):
# VBObject.initFromDictionary(self, d);
# assert(False), "haven't implemented initFromDictionary for {} yet".format(self.VBOBJECT_TYPE())
# #do class specific inits with d;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/TimeSignal1D.py
================================================
from .TimeSignal import *
import math
class TimeSignal1D(TimeSignal):
"""TimeSignal1D (class): A time signal, and a bunch of convenience functions to go with it.
Attributes:
sampling_rate: the sampling rate
x: the time signal
"""
def VBOJECT_TYPE(self):
return 'TimeSignal1D';
def __init__(self, path=None, sampling_rate = None, x=None):
TimeSignal.__init__(self, path=path, sampling_rate=sampling_rate);
if(x is not None):
self.x = x;
#self.initializeBlank(); # will be called by parent
def initializeBlank(self):
TimeSignal.initializeBlank(self);#YES KEEP call through weird loops
self.x = None;
def getSignal(self, resampled=False):
return self.x;
def getSignalSegment(self, time_range):
signal = self.getSignal();
seg_start = int(time_range[0]*self.sampling_rate);
seg_end = int(time_range[1]*self.sampling_rate);
return signal[seg_start:seg_end];
def getFullSignal(self):
return self.x;
def getSampleAtTime(self, f):
prev_sample = self.x[int(math.floor(f))];
next_sample = self.x[int(math.ceil(f))];
sample_progress = f-np.floor(f);
return (next_sample*sample_progress)+(prev_sample*(1.0-sample_progress));
def getSampleAtIndex(self, i):
return self.x[i];
def getDuration(self):
return truediv(len(self.getSignal()), self.sampling_rate);
def setValueRange(self, value_range=None):
if(value_range is None):
value_range = [0,1];
data = self.x[:];
currentscale = np.max(data)-np.min(data);
data = (data/currentscale)*(value_range[1]-value_range[0]);
data = data-np.min(data)+value_range[0]
self.x = data;
def setMaxAbsValue(self, max_abs_val=1.0):
data = self.x[:];
currentscale = np.max(np.fabs(data));
data = (data/currentscale)*max_abs_val;
self.x = data;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/VBMIDI.py
================================================
# %load VisBeat/MidiParse.py
import mido
import numpy as np
import os
# from TimeSignal1D import *
from .Audio import *
from .Event import *
class VBMIDITrack(object):
def __init__(self, track, ticks_per_beat):
self.mido_track = track;
self.name = track.name;
# print('Track {}: {}'.format(i, track.name));
self.tempo = next((msg.tempo for msg in track if msg.type == 'set_tempo'), None);
self.ticks_per_beat = ticks_per_beat;
# self._get_note_on_times();
self.note_on_times = None;
def getBPM(self):
return mido.tempo2bpm(self.tempo);
def getNoteOnTimes(self, include_negative=None):
if(self.note_on_times is None or (include_negative)):
self._get_note_on_times(include_negative = include_negative);
return self.note_on_times;
def _get_note_on_times(self, include_negative = None):
"""
Gets the starting time of each note.
"""
note_times = []
current_time = 0;
for msg in self.mido_track:
if not msg.is_meta:
delta_time = mido.tick2second(msg.time, self.ticks_per_beat, self.tempo)
current_time += delta_time
if msg.type == 'note_on' and msg.velocity > 0:
if (include_negative or current_time>=0):
note_times.append(current_time);
self.note_on_times = np.array(note_times);
def get_note_durations(self, track_num):
note_durations = []
currently_played_notes = {}
current_time = 0
for msg in self.mido_track:
if not msg.is_meta:
delta_time = mido.tick2second(msg.time, self.ticks_per_beat, self.tempo)
current_time += delta_time
if msg.type == 'note_on' and msg.velocity > 0 and msg.note not in currently_played_notes:
currently_played_notes[msg.note] = current_time
#if len(currently_played_notes) > 1:
# print "Number of played notes have reached: ", len(currently_played_notes)
elif msg.type == 'note_off' or (msg.type == 'note_on' and msg.velocity == 0):
duration = current_time - currently_played_notes[msg.note]
note_durations.append((currently_played_notes[msg.note], duration))
currently_played_notes.pop(msg.note)
assert not bool(currently_played_notes), "Finished looping through all messages. There should not be any notes playing at this point."
#print "before sorting: ", note_durations
note_durations.sort(key=lambda x : x[0])
#print "after sorting: ", note_durations
return np.array([ x[1] for x in note_durations ])
def get_mouth_events(self):
# note_times = []
current_time = 0;
number_on = 0;
events = [];
open_buffer = 0.1;
close_buffer = 0.1
last_type = 0;
events.append(Event(start=0, type='mouth_close', weight=1));
for msg in self.mido_track:
if not msg.is_meta:
delta_time = mido.tick2second(msg.time, self.ticks_per_beat, self.tempo)
current_time += delta_time
last_time = events[-1].start;
passed = current_time-last_time;
if msg.type == 'note_on' and msg.velocity > 0:
if(last_type==0):
if(passed>open_buffer):
events.append(Event(start=current_time-open_buffer, type='mouth_closed', weight=0));
events.append(Event(start=current_time, type='mouth_open', weight = truediv(msg.velocity,127)));
number_on = number_on + 1;
last_type=1;
if(msg.type == 'note_off' or (msg.type=='note_on' and msg.velocity == 0)):
if (last_type == 1):
if (passed > close_buffer):
events.append(Event(start=current_time - close_buffer, type='mouth_opened', weight=0));
events.append(Event(start=current_time, type='mouth_close', weight = truediv(msg.velocity,127)));
number_on = number_on-1;
last_type=0;
# assert(number_on>-1);
# if(number_on==0):
return events;
# self.note_on_times = np.array(note_times);
def getNoteOnTimesAsAudio(self, sampling_rate = None, note_sound=None, n_seconds=None):
assert(n_seconds is not None), "must provide n seconds"
if(sampling_rate is None):
sampling_rate = 16000;
if(note_sound is None):
note_sound = Audio.getPing();
s = Audio.Silence(n_seconds=n_seconds, sampling_rate=sampling_rate, name=self.name)
s = s.getWithSoundAdded(note_sound, self.getNoteOnTimes());
return s;
class VBMIDI(TimeSignal1D):
def __init__(self, path=None):
TimeSignal1D.__init__(self, path=path);
self.midi_file = mido.MidiFile(path)
self.tracks = [];
for i, track in enumerate(self.midi_file.tracks):
self.tracks.append(VBMIDITrack(track, self.midi_file.ticks_per_beat));
def getNoteOnTimes(self, include_negative=None):
return self.tracks[-1].getNoteOnTimes(include_negative=include_negative);
def getMouthEvents(self):
return self.tracks[-1].get_mouth_events();
def getNoteOnTimesAsAudio(self, sampling_rate=None, note_sound=None):
s = self.tracks[-1].getNoteOnTimesAsAudio(sampling_rate = sampling_rate, note_sound = note_sound, n_seconds = self.midi_file.length);
if (s.name is None):
s.name = self.getInfo('file_name')
return s;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/VBObject.py
================================================
import os
import json
from .VisBeatImports import *
from .AFuncDict import *
from .AObject import AObject
class VBObject(AObject):
"""VBObject (class): This is a paarent class used to implement common serialization and other functions. There ends
up being three different dictionaries of data.
a_info - for small labels and such. Part of AObject.
a_data - for data to be computed in experiments. I generally use this for things I don't want to automatically
save out to file.
features - these are features tied to the results of functions, and manager classes (e.g. VideoSource) will save
these to disk for future use.
FEATURE_FUNCS is a dictionary mapping the names of features to their corresponding functions.
"""
FEATURE_FUNCS={};
def __init__(self, path=None):
AObject.__init__(self, path=path);
def initializeBlank(self):
AObject.initializeBlank(self);
self.a_info.update({'VBObjectType': self.VBOBJECT_TYPE()});
self.features = AFuncDict(owner=self, name='features');
self.features.functions.update(self.FEATURE_FUNCS);
def saveFeature(self, name, path):
"""Subclasses can implement version of this that will check members for features if those features arent found here."""
return self.features.saveEntry(name=name, path=path);
def saveFeatures(self, path):
return self.features.save(path=path);
def loadFeature(self, name, path):
"""Subclasses can implement version of this that will check whether feature is registered before loading."""
return self.features.loadEntry(name=name, path=path);
def loadFeatures(self, path):
return self.features.load(path=path);
def getFeature(self,name, force_recompute=False, **kwargs):
"""Understood to get the value of a feature. can automatically recompute if feature has registered function."""
params = kwargs;
assert (not kwargs.get('params')), "STILL TRYING TO USE PARAMS INSTEAD OF KWARGS. FIX THIS";
return self.features.getValue(name=name, params=kwargs, force_recompute=force_recompute);
def getFeatureEntry(self, name, params=None, force_recompute=False):
return self.features.getEntry(name=name, params=params, force_recompute=force_recompute);
def getFeatureParams(self, name):
return self.features.getParams(name=name);
def setFeature(self, name, value, params=None):
rval = self.features.setEntry(name=name, d=dict(value=value, params=params));
self.features.setEntryModified(name=name, is_modified=True);
return rval;
def removeFeature(self, name, assert_if_absent=True, set_modified=True):
self.features.removeEntry(name=name, assert_if_absent=assert_if_absent, set_modified=set_modified);
def hasFeature(self, name):
"""Just checks to see if it's there."""
return self.features.hasEntry(name=name);
def getFeatureFunction(self, feature_name):
return self.features.getFunction(name=feature_name);
def getFeaturesList(self):
return self.features.getKeyList();
def getFeatureFunctionsList(self):
return self.features.getFunctionList();
def clearFeatureFiles(self, features_to_clear=None, **kwargs):
if(self.clear_feature_files_func):
self.clear_feature_files_func(self, features_to_clear=features_to_clear, **kwargs);
else:
VBWARN("CLEAR FEATURE FILES FUNCTION HAS NOT BEEN PROVIDED FOR {} INSTANCE".format(self.VBOBJECT_TYPE()));
########### VIRTUAL FUNCTIONS #############
def AOBJECT_TYPE(self):
return 'VBObject';
def VBOBJECT_TYPE(self):
return self.AOBJECT_TYPE();
# ##Example of how these functions should be written ina subclass, for 'AssetManager' class
# def VBOBJECT_TYPE(self):
# return 'AssetManager';
#
# def toDictionary(self):
# d = VBObject.toDictionary(self);
# #serialize class specific members
# return d;
#
# def initFromDictionary(self, d):
# VBObject.initFromDictionary(self, d);
# #do class specific inits with d;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/Video.py
================================================
#VideoVersion#from VisBeatImports import *
from .AObject import *
from .TimeSignal import *
from .Audio import *
from .Warp import *
from .Image import *
import moviepy.editor as mpy
from moviepy.audio.AudioClip import AudioArrayClip as MPYAudioArrayClip
import sys
import math
from operator import truediv
def MPYWriteVideoFile(mpyclip, filename, **kwargs):
temp_audio_filename = get_temp_file_path(final_file_path='TEMP_'+filename+'.m4a', temp_dir_path=Video.VIDEO_TEMP_DIR);
return mpyclip.write_videofile(filename=filename, temp_audiofile= temp_audio_filename, audio_codec='aac', **kwargs);
class Video(TimeSignal):
"""Video (class): A video, and a bunch of convenience functions to go with it.
Attributes:
"""
VIDEO_TEMP_DIR = './'
FEATURE_FUNCS = TimeSignal.FEATURE_FUNCS.copy();
def AOBJECT_TYPE(self):
return 'Video';
def __init__(self, path=None, name=None, num_frames_total=None):
TimeSignal.__init__(self, path=path);
if(name):
self.name = name;
if(path):
self.loadFile(num_frames_total=num_frames_total);
def initializeBlank(self):
TimeSignal.initializeBlank(self);#YES KEEP
self.name = None;
self.sampling_rate = None;
self.audio=None;
self.reader = None;
self.writer = None;
self.num_frames_total=None;
self.reshape=None;
self.meta_data = None;
self.sampling_rate = None;
self.source = None;
# _gui is not saved
self._gui = None;
def _getFrameRate(self):
return self.sampling_rate;
# _gui is from TimeSignal
#
@property
def gui(self):
return self._getGui();
def _getGui(self):
return self._gui;
@gui.setter
def gui(self, value):
self._setGui(value);
def _setGui(self, value):
self._gui = value;
#
def getVersionInfo(self):
"""This is the info to be saved in asset version dictionary"""
d={};
d['name']=self.name;
d['sampling_rate']=self.sampling_rate;
d['num_frames_total']=self.num_frames_total;
d['duration']=self.getDuration();
d['start_time']=self.getStartTime();
d['end_time']=self.getEndTime();
d['meta_data']=self.meta_data;
return d;
def getName(self):
if(self.name is None):
return self.getInfo('file_name');
else:
return self.name;
def getTempDir(self):
if(self.source is not None):
return self.source.getDir('temp');
else:
return Video.VIDEO_TEMP_DIR;
def getStringForHTMLStreamingBase64(self):
svideo = io.open(self.getPath(), 'r+b').read()
encoded = base64.b64encode(svideo)
return "data:video/mp4;base64,{0}".format(encoded.decode('ascii'));
def n_frames(self):
if(not self.num_frames_total):
self.num_frames_total = self.calcNumFramesTotal();
return self.num_frames_total;
def getDuration(self):
return truediv(self.n_frames(), self.sampling_rate);
def getStartTime(self):
return 0;
def getEndTime(self):
return self.getDuration();
def getMPYClip(self, get_audio=True):
return mpy.VideoFileClip(self.getPath(), audio=get_audio);
def getAudio(self):
return self.audio;
def loadFile(self, file_path=None, num_frames_total=None):
if (file_path):
self.setPath(file_path=file_path);
if ('file_path' in self.a_info):
self.reader = imageio.get_reader(self.a_info['file_path'], 'ffmpeg');
self.meta_data = self.reader.get_meta_data();
self.sampling_rate = self.meta_data['fps'];
if (num_frames_total is not None):
self.num_frames_total = num_frames_total;
else:
self.num_frames_total = self.calcNumFramesTotal();
try:
self.audio = Audio(self.a_info['file_path']);
self.audio.name =self.name;
#except RuntimeError:
except Exception:
print(("Issue loading audio for {}".format(self.a_info['file_path'].encode('utf-8'))));
self.audio = Audio(sampling_rate=16000);
self.audio.x = np.zeros(int(np.ceil(self.audio.sampling_rate*self.getDuration())));
def openVideoWriter(self, output_file_path, fps=None):
if('outputs' not in self.a_info):
self.a_info['outputs'] = [];
out_fps = fps;
if(not out_fps):
out_fps=self.sampling_rate;
make_sure_dir_exists(output_file_path);
self.writer = imageio.get_writer(output_file_path, 'ffmpeg', macro_block_size = None, fps = out_fps);
self.a_info['outputs'].append(output_file_path);
def closeVideoWriter(self):
self.writer.close();
self.writer = None;
def getFrameShape(self):
fs=self.getInfo('frame_shape');
if(fs is not None):
return fs;
else:
self.setInfo(label='frame_shape', value=self.reader.get_data(0).shape);
return self.getInfo('frame_shape');
def calcNumFramesTotal(self):
#assert(False)
print(("Calculating frames for {}...".format(self.name)))
valid_frames = 0
example_frame = self.reader.get_data(0);
self.setInfo(label='frame_shape',value=example_frame.shape);
# https://stackoverflow.com/questions/54778001/how-to-to-tackle-overflowerror-cannot-convert-float-infinity-to-integer
#for i in range(1, self.reader.get_length()):
for i in range(1, self.reader.count_frames()):
try:
self.reader.get_data(i);
except imageio.core.format.CannotReadFrameError as e:
break
valid_frames += 1
print("Done.")
return valid_frames
def readFrameBasic(self, i):
"""You should basically never call this"""
fi=i;
if(fi<0):
fi=0;
if(fi>(self.num_frames_total-1)):
fi=(self.num_frames_total-1);
return np.asarray(self.reader.get_data(int(fi)));
def getFrame(self, f):
return self.readFrameBasic(round(f));
def getFrameFromTime(self, t):
f = t*self.sampling_rate;
return self.getFrame(f=f);
def getFrameLinearInterp(self, f):
if(isinstance(f,int) or f.is_integer()):
return self.readFrameBasic(int(f));
prev_frame = self.readFrameBasic(math.floor(f));
next_frame = self.readFrameBasic(math.ceil(f));
frame_progress = f-np.floor(f);
rframe = (next_frame*frame_progress)+(prev_frame*(1.0-frame_progress));
return rframe.astype(prev_frame.dtype);
def writeFrame(self, img):
if self.writer.closed:
print('ERROR: Vid writer object is closed.')
else:
self.writer.append_data(img.astype(np.uint8))
def play(self):
if(ISNOTEBOOK):
print("Playing video:")
video = io.open(self.getPath(), 'r+b').read()
encoded = base64.b64encode(video)
vidhtml=HTML(data=''''''.format(encoded.decode('ascii')));
IPython.display.display(vidhtml);
# return vidhtml;
else:
print("HOW TO PLAY VIDEO? NOT A NOTEBOOK.")
def show(self):
self.play();
def write(self, output_path, output_sampling_rate=None):
assert output_path, "MUST PROVIDE OUTPUT PATH FOR VIDEO"
sampling_rate = output_sampling_rate;
if(not sampling_rate):
sampling_rate=self.sampling_rate;
tempfilepath = get_temp_file_path(final_file_path=output_path, temp_dir_path=self.getTempDir());
self.openVideoWriter(output_file_path=tempfilepath, fps=output_sampling_rate);
duration = self.getDuration();
nsamples = sampling_rate*duration;
old_frame_time = truediv(1.0,self.sampling_rate);
frame_start_times = np.linspace(0,self.getDuration(),num=nsamples,endpoint=False);
frame_index_floats = frame_start_times*self.sampling_rate;
start_timer=time.time();
last_timer=start_timer;
fcounter=0;
for nf in range(len(frame_index_floats)):
self.writeFrame(self.getFrame(frame_index_floats[nf]));
fcounter+=1;
if(not (fcounter%50)):
if((time.time()-last_timer)>10):
last_timer=time.time();
print(("{}%% done after {} seconds...".format(100.0*truediv(fcounter,len(frame_index_floats)), last_timer-start_timer)));
self.closeVideoWriter();
rvid = Video.CreateFromVideoAndAudio(video_path=tempfilepath, audio_object=self.audio, output_path=output_path);
os.remove(tempfilepath);
return rvid;
def VideoClip(self, start=None, end=None, name=None):
from . import VideoClip
if(start is None):
start = 0;
if(end is None):
end = self.getDuration();
clip = VideoClip.VideoClip(video=self, start=start, end=end);
if(name):
clip.name=name;
return clip;
def getImageFromFrame(self, i):
rimage = Image(data=self.getFrame(i));
rimage.setInfo(label='parent_video', value=self.getInfo('file_path'));
rimage.setInfo(label='frame_number',value=i);
return rimage;
def getImageFromTime(self, t):
rimage = Image(data=self.getFrameFromTime(t));
rimage.setInfo(label='parent_video', value=self.getInfo('file_path'));
rimage.setInfo(label='frame_time', value=t);
return rimage;
# def getFrameShape(self):
# return self.getImageFromFrame(0).getShape();
def writeResolutionCopyFFMPEG(self, path, max_height=None):
if(max_height is None):
max_height=self.getFrameShape()[0];
mpc = self.getMPYClip();
clip_resized = mpc.resize(height=max_height); # make the height 360px ( According to moviePy documenation The width is then computed so that the width/height ratio is conserved.)
if((clip_resized.size[0]%2)>0):
clip_resized=clip_resized.crop(x1=0,width=clip_resized.size[0]-1);
# clip_resized.write_videofile(path);
MPYWriteVideoFile(clip_resized, path);
rvid = Video(path);
return rvid;
def writeFFMPEG(self, output_path):
mpc = self.getMPYClip();
# mpc.write_videofile(output_path, preset='fast', codec='mpeg4');
MPYWriteVideoFile(mpc, output_path, preset='fast', codec='mpeg4')
rvid = Video(output_path);
return rvid;
def writeResolutionCopy(self, path, max_height=None, reshape=None, input_sampling_rate_factor = None, output_sampling_rate=None):
print((self.getPath()))
if(input_sampling_rate_factor is not None):
original_sampling_rate = self.sampling_rate;
self.sampling_rate=input_sampling_rate_factor*self.sampling_rate;
original_audio_sampling_rate = self.audio.sampling_rate;
self.audio.sampling_rate=self.audio.sampling_rate*input_sampling_rate_factor;
output_path = path;
inshape = self.getFrameShape();
if(reshape==True):
imshape = [inshape[1],inshape[0],inshape[2]];
outshape = None;
if(max_height and (max_height10):
last_timer=time.time();
print(("{}%% done after {} seconds...".format(100.0*truediv(fcounter,len(frame_index_floats)), last_timer-start_timer)));
self.closeVideoWriter();
rvid = Video.CreateFromVideoAndAudio(video_path=tempfilepath, audio_object=self.audio, output_path=output_path);
os.remove(tempfilepath);
if(input_sampling_rate_factor is not None):
#return original_sampling_rate
self.sampling_rate=original_sampling_rate;
self.audio.sampling_rate = original_audio_sampling_rate;
return rvid;
def writeWarped(self, output_path, warp, output_sampling_rate=None, output_audio=None, bitrate=None, vbmark = True, max_time = None, **kwargs):
sampling_rate = output_sampling_rate;
if (not sampling_rate):
sampling_rate = self.sampling_rate;
duration = self.getDuration();
old_frame_time = truediv(1.0, self.sampling_rate);
target_start = warp.getTargetStart();
target_end = warp.getTargetEnd();
target_duration = target_end - target_start;
if(max_time is not None and target_duration>max_time):
target_duration = max_time;
target_end = target_start+max_time;
print((
"target start: {}\ntarget end: {}\ntarget duration: {}".format(target_start, target_end, target_duration)));
new_n_samples = target_duration * sampling_rate;
target_start_times = np.linspace(target_start, target_end, num=new_n_samples, endpoint=False);
unwarped_target_times = [];
for st in target_start_times:
unwarped_target_times.append(warp.warpTargetTime(st));
frame_index_floats = np.true_divide(np.array(unwarped_target_times), old_frame_time);
tempfilepath = get_temp_file_path(final_file_path=output_path, temp_dir_path=Video.VIDEO_TEMP_DIR);
self.openVideoWriter(output_file_path=tempfilepath, fps=output_sampling_rate, **kwargs);
start_timer = time.time();
last_timer = start_timer;
fcounter = 0;
if(vbmark):
vbmarker = self.getImageFromFrame(0)._vbmarker();
for nf in range(len(frame_index_floats)):
try:
nwfr = self.getFrame(frame_index_floats[nf]);
if(vbmark):
nwfrm = Image(data=nwfr);
nwfrm._splatAtPixCoord(**vbmarker);
nwfr = nwfrm._pixels_uint;
self.writeFrame(nwfr);
except ValueError:
print(("VALUE ERROR ON WRITEFRAME {}".format(frame_index_floats[nf])));
self.writeFrame(self.getFrame(math.floor(frame_index_floats[nf])));
fcounter += 1;
if (not (fcounter % 50)):
if ((time.time() - last_timer) > 10):
last_timer = time.time();
print(("{}%% done after {} seconds...".format(100.0 * truediv(fcounter, len(frame_index_floats)),
last_timer - start_timer)));
self.closeVideoWriter();
silent_warped_vid = Video(tempfilepath);
if (not output_audio):
output_audio = self.getAudio();
cropped_output_audio = output_audio.AudioClip(start=target_start, end=target_end);
if ((self.getInfo('max_height') is None) and (bitrate is None)):
use_bitrate = "20000k";
print(('Using bitrate of {}'.format(use_bitrate)));
rvid = Video.CreateFromVideoAndAudioObjects(video=silent_warped_vid, audio=cropped_output_audio,
output_path=output_path, bitrate=use_bitrate);
elif (bitrate is 'regular'):
rvid = Video.CreateFromVideoAndAudioObjects(video=silent_warped_vid, audio=cropped_output_audio,
output_path=output_path);
else:
rvid = Video.CreateFromVideoAndAudioObjects(video=silent_warped_vid, audio=cropped_output_audio,
output_path=output_path, bitrate=bitrate);
os.remove(tempfilepath);
rvid.setInfo(label='warp_used', value=warp);
return rvid;
def getVersionLabel(self):
return self.getInfo('version_label');
def getWarpsDir(self):
if(self.source is None):
return self.getTempDir();
version_label = self.getVersionLabel()
return self.source.getWarpsDir(version_label=version_label);
def getWithBeginningCroppedToAudio(self, target):
if(isinstance(target, Audio)):
B=target;
else:
B=target.getAudio();
A = self.getAudio();
AB = A.getShiftAmountTo(B);
BA = B.getShiftAmountTo(A);
if(AB n_audio_samples_sig):
nreps = math.ceil(truediv(n_audio_samples_in_vid, n_audio_samples_sig));
if (is_stereo):
audio_sig = np.concatenate(
(audio_sig, np.zeros((2, n_audio_samples_in_vid - n_audio_samples_sig))),
axis=1);
else:
audio_sig = np.tile(audio_sig, (int(nreps)));
audio_sig = audio_sig[:int(n_audio_samples_in_vid)];
if (is_stereo):
# reshapex = np.reshape(audio_sig, (audio_sig.shape[1], audio_sig.shape[0]), order='F');
reshapex = np.transpose(audio_sig);
audio_clip = MPYAudioArrayClip(reshapex, fps=audio_sampling_rate); # from a numeric arra
else:
reshapex = audio_sig.reshape(len(audio_sig), 1);
reshapex = np.concatenate((reshapex, reshapex), axis=1);
audio_clip = MPYAudioArrayClip(reshapex, fps=audio_sampling_rate); # from a numeric arra
video_clip = video_object.getMPYClip();
video_clip = video_clip.set_audio(audio_clip);
# video_clip.write_videofile(output_path,codec='libx264', write_logfile=False);
if (bitrate is None):
# video_clip.write_videofile(output_path, codec=codec, write_logfile=False);
MPYWriteVideoFile(video_clip, output_path, codec=codec, write_logfile=False);
else:
MPYWriteVideoFile(video_clip, output_path, codec=codec, write_logfile=False, bitrate=bitrate);
# video_clip.write_videofile(output_path, codec=codec, write_logfile=False, bitrate=bitrate);
if (return_vid):
return Video(output_path);
else:
return True;
@staticmethod
def CreateByStackingVideos(video_objects=None, video_paths=None, output_path=None, audio = None, concatdim = 0, force_recompute=True, **kwargs):
assert output_path, "MUST PROVIDE OUTPUT PATH FOR VIDEO"
if(not force_recompute):
if(os.path.isfile(output_path)):
return Video(path=output_path);
matchdim = (concatdim+1)%2;
vids=[];
if(video_objects is not None):
vids=video_objects;
if(video_paths is not None):
for vp in video_paths:
vids.append(Video(path=video_paths));
output_path=output_path.encode(sys.getfilesystemencoding()).strip();
make_sure_dir_exists(output_path);
basevid = vids[0];
if(audio is None):
audio = basevid.audio;
sampling_rate = basevid.sampling_rate;
tempfilepath = get_temp_file_path(final_file_path=output_path, temp_dir_path=vids[0].getTempDir());
basevid.openVideoWriter(output_file_path=tempfilepath, fps=sampling_rate);
duration = basevid.getDuration();
nsamples = sampling_rate*duration;
old_frame_time = truediv(1.0,sampling_rate);
#frame_start_times = np.linspace(self.getStartTime(),self.getEndTime(),num=nsamples,endpoint=False);
frame_start_times = np.linspace(0,duration,num=nsamples,endpoint=False);
#frame_index_floats = frame_start_times/old_frame_time;
frame_index_floats = frame_start_times*sampling_rate;
for nf in range(len(frame_index_floats)):
frameind = frame_index_floats[nf];
newframe = basevid.getFrame(frameind);
for vn in range(1,len(vids)):
addpart = vids[vn].getFrame(frameind);
partsize = np.asarray(addpart.shape)[:];
cumulsize = np.asarray(newframe.shape)[:];
if(partsize[matchdim]!=cumulsize[matchdim]):
sz = partsize[:];
sz[matchdim]=cumulsize[matchdim];
addpart = sp.misc.imresize(addpart, size=sz);
newframe = np.concatenate((newframe, addpart), concatdim);
basevid.writeFrame(newframe);
basevid.closeVideoWriter();
rvid = Video.CreateFromVideoAndAudio(video_path=tempfilepath, audio_object=audio, output_path=output_path, **kwargs);
os.remove(tempfilepath);
return rvid;
@staticmethod
def CreateFromVideoAndAudioPaths(video_path, audio_path, output_path, return_vid = True, **kwargs):
return Video.CreateFromVideoAndAudio(video_path=video_path, audio_path=audio_path, output_path=output_path,return_vid=return_vid, **kwargs);
@staticmethod
def CreateFromVideoAndAudioObjects(video, audio, output_path, clip_to_video_length=True, return_vid = True, **kwargs):
return Video.CreateFromVideoAndAudio(video_object=video, audio_object=audio, output_path=output_path, clip_to_video_length=clip_to_video_length, return_vid = return_vid, **kwargs);
def _getDefaultPeakPickingTimeParams(self, **kwargs):
single_frame = np.true_divide(1.0, self._getFrameRate());
time_params = dict(
pre_max_time=2.0 * single_frame,
post_max_time=2.0 * single_frame,
pre_avg_time=5.0 * single_frame,
post_avg_time=5.0 * single_frame,
wait_time=2.0 * single_frame,
delta=0.015,
)
time_params.update(kwargs);
return time_params;
# ###################
# FEATURE
def getFrameIndexes(self, force_recompute=False):
feature_name = 'frame_indexes';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = dict();
duration = self.getDuration();
nsamples = self.sampling_rate * duration;
frame_start_times = np.linspace(0, duration, num=nsamples, endpoint=False);
value = frame_start_times * self.sampling_rate;
self.setFeature(name=feature_name, value=value, params=params);
return self.getFeature(feature_name);
def getFeaturesList(self):
return super(Video, self).getFeaturesList()+self.audio.getFeaturesList();
def getVideoFeaturesList(self):
return super(Video, self).getFeaturesList();
def getFeatureFunctionsList(self):
return super(Video, self).getFeatureFunctionsList()+self.audio.getFeatureFunctionsList();
def getFeatureSourceType(self, name):
"""returns whether video or audio feature, instead of parent version which returns true or false"""
vidhas = super(Video, self).hasFeature(name=name);
if(vidhas):
return 'video';
audiohas = self.audio.hasFeature(name=name);
if(audiohas):
return 'audio';
return None;
def getFeature(self, name, force_recompute=False, **kwargs):
"""Returns None if feature is not already computed, and feature name is not implemented and registered with FEATURE_FUNCS"""
params = kwargs;
assert(not kwargs.get('params')), "STILL TRYING TO USE PARAMS INSTEAD OF KWARGS. FIX THIS";
ftry = super(Video, self).getFeature(name=name, force_recompute=force_recompute, **kwargs);
if(ftry is not None):
return ftry;
else:
return self.audio.getFeature(name=name, force_recompute=force_recompute, **kwargs);
Video.FEATURE_FUNCS['frame_indexes']=Video.getFrameIndexes;
from . import Video_CV;
if(Video_CV.USING_OPENCV):
Video.FEATURE_FUNCS.update(Video_CV.FEATURE_FUNCS);
Video.USING_OPENCV = Video_CV.USING_OPENCV;
Video.localRhythmicSaliencyFunction = Video_CV.localRhythmicSaliencyFunction
Video.visualBeatFunction = Video_CV.visualBeatFunction
Video.cvGetGrayFrame = Video_CV.cvGetGrayFrame;
Video.getImageFromFrameGray = Video_CV.getImageFromFrameGray;
Video.plotVisualBeats = Video_CV.plotVisualBeats;
Video.loadFlowFeatures = Video_CV.loadFlowFeatures;
Video.getVisualBeats = Video_CV.getVisualBeats
Video.getLocalRhythmicSaliency = Video_CV.getLocalRhythmicSaliency;
Video.getDirectogram = Video_CV.getDirectogram;
Video.getDirectogramPowers = Video_CV.getDirectogramPowers;
Video.getVisibleImpactEnvelope = Video_CV.getVisibleImpactEnvelope;
Video.getVisibleImpactEnvelopePowers = Video_CV.getVisibleImpactEnvelopePowers;
Video.getVisibleImpacts = Video_CV.getVisibleImpacts;
Video.getVisualBeats = Video_CV.getVisualBeats;
# Video.getBackwardVisualBeats = Video_CV.getBackwardVisualBeats;
# Video.getForwardVisualBeats = Video_CV.getForwardVisualBeats;
Video.getBackwardVisibleImpactEnvelope = Video_CV.getBackwardVisibleImpactEnvelope;
Video.getBothWayVisibleImpactEnvelope = Video_CV.getBothWayVisibleImpactEnvelope;
Video.getForwardVisibleImpactEnvelope = Video_CV.getForwardVisibleImpactEnvelope;
Video.getDirectionalFlux = Video_CV.getDirectionalFlux;
Video.getVisualTempogram = Video_CV.getVisualTempogram;
Video.getCutEvents = Video_CV.getCutEvents;
Video.computeImpactEnvelope = Video_CV.computeImpactEnvelope;
Video.computeDirectogramPowers = Video_CV.computeDirectogramPowers;
Video.visualBeatsFromEvents = Video_CV.visualBeatsFromEvents;
Video.plotVisualBeats = Video_CV.plotVisualBeats;
Video.plotImpactEnvelope = Video_CV.plotImpactEnvelope;
Video.plotVisibleImpacts = Video_CV.plotVisibleImpacts;
Video.getVisualBeatSequences = Video_CV.getVisualBeatSequences;
Video.printVisualBeatSequences = Video_CV.printVisualBeatSequences;
Video.getVisualBeatTimes = Video_CV.getVisualBeatTimes;
Video.findAccidentalDanceSequences = Video_CV.findAccidentalDanceSequences;
Video.plotEvents = Video_CV.plotEvents;
# Video. = Video_CV.
# Video. = Video_CV.
# Video. = Video_CV.
# Video. = Video_CV.
# Video. = Video_CV.
# Video. = Video_CV.
else:
AWARN("Was not able to add functions that use OpenCV! Check OpenCV instalation and try again?");
from .vbgui import BeatGUI
if(BeatGUI.VIEWER_INSTALLED):
def getEvents(self, **kwargs):
time_params = self._getDefaultPeakPickingTimeParams();
time_params.update(kwargs)
vbeats = self.getFeature('visual_beats', force_recompute=True, **time_params);
return vbeats;
def getEventList(self, **kwargs):
events = self.getEvents(**kwargs);
return EventList(events=events);
def runBeatGUIOnAudio(self):
audio = self.getAudio();
self.gui.run(local_saliency=audio.getLocalRhythmicSaliency(), frame_rate = audio._getFrameRate(), eventlist = audio.getEventList());
def runGUI(self, local_saliency=None, frame_rate = None, eventlist = 'default', frame_offset=None):
self.gui.run(local_saliency=local_saliency, frame_rate=frame_rate, eventlist=eventlist, frame_offset=frame_offset);
Video._getGui = BeatGUI.media_GUI_func;
Video.runGUI = runGUI;
Video.getEvents = getEvents;
Video.getEventList = getEventList;
Video.runBeatGUIOnAudio = runBeatGUIOnAudio;
else:
AWARN("BeatGUI not installed");
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/VideoClip.py
================================================
from .Video import *
from .AudioClip import *
class VideoClip(Video):
"""VideoClip (class): A segment of a video, and a bunch of convenience functions to go with it.
Attributes:
start: The name of the video
end: The framerate of the video
"""
def AOBJECT_TYPE(self):
return 'VideoClip';
def __init__(self, video=None, start=None, end=None, clip_to_frame=True, path=None):
"""If a video is provided, we don't want to reload the video from disk. If a path is provided, we have no choice.
"""
assert(not (video and path)), "provided both video object and path to VideoClip constructor."
assert((start is not None) and (end is not None)), "must provide start time and end time to AudioClip constructor"
Video.__init__(self, path = path);
self.initializeBlank();
self.start = start;
self.end = end;
if(video):
self.setPath(video.getPath());
self.reader = video.reader;
#self.writer = None; #this only comes up if we write later
self.sampling_rate=video.sampling_rate;
self.num_frames_total=video.num_frames_total;
time_per_frame=truediv(1.0,self.sampling_rate);
if(clip_to_frame):
self.start=time_per_frame*math.floor(truediv(self.start,time_per_frame));
self.end=time_per_frame*math.floor(truediv(self.end,time_per_frame));
if(video.name):
self.name = video.name+"_{}_{}".format(start,end);
self.audio = video.audio.AudioClip(start=start, end=end);
else:
assert(False),"must provide video to VideoClip init"
def initializeBlank(self):
Video.initializeBlank(self);
self.start = None;
self.end = None;
# def readFrameBasic(self, i):
# return Video.getFrame(self, float(i)+self.start);
def getFrameLinearInterp(self, f):
return Video.getFrameLinearInterp(self, float(f)+self.start*self.sampling_rate);
def getFrame(self, f):
return Video.getFrame(self, float(f)+self.start*self.sampling_rate);
def getDuration(self, round_to_frames=False):
if(not round_to_frames):
return self.end-self.start;
else:
return truediv(self.n_frames(), self.sampling_rate);
def n_frames(self):
#return self.getLastFrameIndex()-self.getFirstFrameIndex();
return math.ceil((self.end-self.start)*self.sampling_rate);
# def getFirstFrameIndex(self):
# return math.floor(self.start*self.sampling_rate);
#
# def getLastFrameIndex(self):
# #I think floor is still right here, because the times mark beginnings of frames
# return math.floor(self.end*self.sampling_rate);
def getStartTime(self):
return self.start;
def getEndTime(self):
return self.end;
def getMPYClip(self, get_audio=True):
return mpy.VideoFileClip(self.getPath(), audio=get_audio).subclip(self.getStartTime(), self.getEndTime());
def play(self):
if(ISNOTEBOOK):
print("Playing video:")
IPython.display.display(self.getMPYClip().ipython_display(fps=self.sampling_rate, maxduration=self.getDuration()+1));
else:
print("HOW TO PLAY VIDEO? NOT A NOTEBOOK.")
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/VideoSource.py
================================================
from .VisBeatImports import *
from .Video import *
from .AFileManager import AFileManager
try:
import youtube_dl
except ImportError:
AWARN('You need to install youtube-dl to use parts of VideoSource class that pull from YouTube. Try running:\npip install youtube-dl')
def safe_file_name(input_string):
return ''.join([i if ord(i) < 128 else '_' for i in input_string]);
class VideoSource(AFileManager):
"""Video (class): A video, and a bunch of convenience functions to go with it.
Attributes:
name: The name of the video
sampling_rate: The framerate of the video
audio: an Audio object, the audio for the video
"""
VIDEO_TEMP_DIR = './'
def getJSONName(self):
return self.AOBJECT_TYPE()+".json";
def AOBJECT_TYPE(self):
return 'VideoSource';
def __init__(self, path, name=None, source_location=None, VideoClass = None, **kwargs):
"""
:param path: either the path to a json, or the path to a directory containing 'VideoSource.json',
or the path to a directory where said json should be created.
:param name: name for video
:param source_location: can be a path to a video file, or a youtube source from which to pull a video file
:param VideoClass: visbeat.Video by default, but can be changed if you are using a custom subclass.
Must be a subclass of visbeat.Video, and must be constructable with VideoClass(path)
"""
AFileManager.__init__(self, path=path);
if(VideoClass is not None):
self.VideoClass = VideoClass;
self.setSource(source_location=source_location, assert_valid=None, **kwargs);
# if (self.name is None):
# self.name = os.path.splitext(os.path.basename(path))[0]
@staticmethod
def NewVideoSource(destination, name, source_location=None, VideoClass = None, **kwargs):
vsdir = os.path.join(destination, name+os.sep);
make_sure_dir_exists(vsdir);
print(("Video source at {}".format(vsdir)));
return VideoSource(path=vsdir, name=name, source_location=source_location, **kwargs);
def initializeBlank(self):
AFileManager.initializeBlank(self);
self.source_location = None;
self.name = None;
self.video_file_name = None;
self.title_safe = None;
self.youtube_info_dict = None;
self.versions_info = {};
#
self.VideoClass = Video;
def toDictionary(self):
d = AFileManager.toDictionary(self);
d['source_location']=self.source_location;
if(self.name):
d['name']=self.name;
if(self.video_file_name):
d['video_file_name']=self.video_file_name;
if(self.title_safe):
d['title_safe']=self.title_safe;
if(self.youtube_info_dict):
d['youtube_info_dict']=self.youtube_info_dict;
if(self.versions_info):
d['versions_info']=self.versions_info;
return d;
def initFromDictionary(self, d):
AFileManager.initFromDictionary(self, d);
self.source_location = d['source_location'];
self.name = d.get('name');
self.video_file_name = d.get('video_file_name');
self.title_safe = d.get('title_safe');
self.youtube_info_dict = d.get('youtube_info_dict');
self.versions_info=d.get('versions_info');
if(self.versions_info is None):
self.versions_info = {};
#do class specific inits with d;
def initWithPath(self, path=None, clear_temp=None):
AFileManager.initWithPath(self, path=path, clear_temp=clear_temp);
self.setDir('versions', pathstring(self.getDirectoryPath() + os.sep + "Versions" + os.sep));
self.setDir('warps', pathstring(self.getDir('versions')+ os.sep + "Warps" + os.sep));
# self.setDir('midi', pathstring(self.getDirectoryPath() + os.sep + "MIDI" + os.sep));
# self.setDir('music', pathstring(self.getDirectoryPath() + os.sep + "Music" + os.sep));
self.setFeaturesDir();
def setFeaturesDir(self, features_dir=None):
if (features_dir is None):
self.setDir('features', pathstring(self.getDir('data') + os.sep + "Features" + os.sep))
else:
self.setDir('features', features_dir);
def getName(self):
"""
Gets name if set. If not set, returns file name without extension.
:return:
"""
if(self.name is not None):
return self.name;
elif(self.video_file_name is not None):
return os.path.splitext(self.video_file_name)[0];
else:
return None;
###################
@staticmethod
def _versionLabelString(version_label=None):
if (version_label and version_label != 'Full'):
return str(version_label);
else:
return 'Full';
@staticmethod
def _versionGroupString(version_group=None):
if (version_group is None):
version_group = 'Original';
return version_group;
@staticmethod
def _getVersionLabelDirName(version_label=None):
if(isinstance(version_label, int)):
return ("maxheight_{}".format(version_label));
else:
return "Full";
def getVersionPath(self, version_label=None, version_group=None):
"""
Get path to version of video (path to video file). Return None if version has not been added.
:param version_label:
:return:
"""
return self.getVersionInfo(version_label=version_label, version_group=version_group, info_label='path');
def getDirForVersion(self, version_label=None, version_group=None):
vdir = self.getDir('versions') + os.sep + self._versionGroupString(version_group) + os.sep + self._getVersionLabelDirName(version_label)+os.sep;
return vdir;
def getVersionInfo(self, version_label, version_group=None, info_label=None):
"""
Get info about a version of the video
:param version_label:
:param info_label:
:return:
"""
assert(info_label is not None), "should provide info_label to getVersionInfo()"
d = self.getVersionDictionary(version_label=version_label, version_group=version_group);
if(d is not None):
return d.get(info_label);
else:
return None;
def getVersionDictionary(self, version_label=None, version_group=None):
if(version_group is None):
version_group='Original';
vis_d=self.versions_info.get(version_group);
if(vis_d is not None):
return vis_d.get(VideoSource._versionLabelString(version_label));
else:
return None;
def setVersionDictionary(self, version_label=None, version_group=None, d=None):
if(version_group is None):
version_group='Original';
vis_d=self.versions_info.get(version_group);
if(vis_d is None):
self.versions_info[version_group]={};
vis_d=self.versions_info.get(version_group);
vis_d[VideoSource._versionLabelString(version_label)]=d;
return;
def setVersionInfo(self, version_label=None, version_group=None, video_path=None, **kwargs):
version_dict = self.getVersionDictionary(version_label=version_label, version_group=version_group);
if(version_dict is None):
self.setVersionDictionary(version_label=version_label, version_group=version_group, d={});
version_dict = self.getVersionDictionary(version_label=version_label, version_group=version_group);
if(video_path is not None):
version_dict.update({'path':str(pathstring(video_path))});
if(kwargs is not None):
version_dict.update(kwargs);
####################
def hardSave(self):
if (os.path.isfile(self.getJSONPath())):
os.rename(self.getJSONPath(), self.getDir('backup') + os.sep + self.AOBJECT_TYPE() + ".json");
self.writeToJSON(self.getJSONPath());
def save(self):
if (self.getInfo('block_writing_to_json')):
return;
self.hardSave();
####################
# def removeAllVersionFiles(self, asset_manager=None):
# AWARN("This should wipe the directory, ya?")
# # AWARN("Remove all version files does not remove features and vis images! This still needs to be implemented!")
# # for vtype in self.versions_info:
# # for v in self.versions_info.get(vtype):
# # # print(self.versions_info.get(vtype).get(v));
# # vpath = self.versions_info.get(vtype).get(v).get('path');
# # assert(vpath), "version {} did not have path".format(vtype)
# # print(vpath)
# # if(os.path.isfile(vpath)):
# # print("REMOVING {}".format(vpath))
# # os.remove(vpath);
# # if(asset_manager is not None and vtype=='Original'):
# # if(v=='Full'):
# # rs=None;
# # else:
# # rs = int(v);
# # asset_manager.removeFeaturesForLinkRes(link=self, max_height=rs);
# # return True;
# def removeFeaturesForRes(self, max_height=None):
# v = self.getVersionVideo(name=link.name, max_height = max_height);
# v.clearFeatureFiles(features_to_clear=['all', 'each']);
#
#
# def removeFeatureFilesForVideo(self, video, features_to_remove=None):
# if(features_to_remove is None):
# return;
# if(not isinstance(features_to_remove, list)):
# features_to_remove=[features_to_remove];
# for f in features_to_remove:
# self.removeFeatureFileForVideo(video=video, feature_name=f);
#
#
# def removeFeatureFileForVideo(self, video, feature_name):
# AWARN("still need to implement removeFeatureFileForVideo. Should just empty corresponding directory. Also implement 'each' that removes all.")
# # if(feature_name=='each'):
# # return self.removeFeatureFilesForVideo(video=video, features_to_remove=video.getFeatureFunctionsList());
# # max_height = video.getInfo(label='max_height');
# # link = self.hasLinkWithName(name=video.name);
# # source_type=video.getFeatureSohahurceType(feature_name);
# # ipath = self.getFeaturePathForLink(feature_name=feature_name, link=link, max_height=max_height, source_type=source_type);
# # if(os.path.isfile(ipath)):
# # print("REMOVING {}".format(ipath));
# # os.remove(ipath);
#
# def removeFeatureFiles(self, video, feature_name):
# if(feature_name=='each'):
# AWARN("IMPLEMENT DELETE FEATURE DIR AND CREATE CLEAN");
# version_label = video.getInfo(label='version_label');
# AWARN("IMPLEMENT DELETE {} FOR VERSION_LABEL {}".format(feature_name, version_label));
# # ipath = self.getFeaturePathForLink(feature_name=feature_name, link=link, max_height=max_height, source_type=source_type);
# # if(os.path.isfile(ipath)):
# # print("REMOVING {}".format(ipath));
# # os.remove(ipath);
#
# def removeVersion(self, version_label=None, remove_files=True):
# AWARN("Remove Resolution does not remove features! This still needs to be implemented!")
# for vtype in self.versions_info:
# v = self.versions_info.get(vtype).get(VideoSource._versionLabelString(version_label));
# if(v is not None):
# vpath = v.get('path');
# if(os.path.isfile(vpath)):
# print("REMOVING {}".format(vpath))
# os.remove(vpath);
# self.versions_info.get(vtype).pop(VideoSource._versionLabelString(version_label), None);
# return True;
#
# def copyResolutionTo(self, version_label=None, output_dir=None):
# assert(output_dir)
# for vtype in self.versions_info:
# v = self.versions_info.get(vtype).get(VideoSource._versionLabelString(version_label));
# if(v is not None):
# vpath = v.get('path');
# if(os.path.isfile(vpath)):
# opath = os.path.join(output_dir,(vtype+'_'+VideoSource._versionLabelString(version_label)+self.video_file_name));
# print("COPYING {} to {}".format(vpath,opath));
# shutil.copy2(vpath, opath);
# return True;
#
# def copyAssetsTo(self, output_dir=None, asset_manager=None):
# for vtype in self.versions_info:
# output_type_dir=pathstring(output_dir+os.sep+vtype+os.sep);
# make_sure_dir_exists(output_type_dir);
# for v in self.versions_info.get(vtype):
# output_a_dir = pathstring(output_type_dir+os.sep+v+os.sep);
# make_sure_dir_exists(output_a_dir);
# # print(self.versions_info.get(vtype).get(v));
# vpath = self.versions_info.get(vtype).get(v).get('path');
# if(vpath and os.path.isfile(vpath)):
# print("copying {} to {}".format(vpath, output_a_dir));
# shutil.copy2(vpath, output_a_dir);
# if(asset_manager is not None and vtype=='Original'):
# if(v=='Full'):
# rs=None;
# else:
# rs = int(v);
# asset_manager.saveFeaturesForVersion(version_label=rs, output_dir = output_a_dir);
def getWarpsDir(self, version_label=None):
warpdir = self.getDir('warps');
resdir = self._getVersionLabelDirName(version_label=version_label);
rdir = pathstring(warpdir + os.sep + resdir + os.sep);
make_sure_path_exists(rdir);
return rdir;
# ############################# FROM ASSETMANAGER #######################
def getVersion(self, max_height=None, get_if_missing=True, load_features=True, **kwargs):
"""
Gets a version of the video with maximum height max_height. This function contains logic to decide whether/when
to pull the video. Use pullVersion to force pulling that overwrite's existing assets.
:param max_height:
:param get_if_missing:
:return:
"""
vpath = self.getVersionPath(version_label=max_height);
if(vpath and os.path.isfile(vpath)):
num_frames_total = self.getVersionInfo(version_label=max_height, info_label='num_frames_total');
if(num_frames_total):
v = self.RegisteredVideo(path=vpath, version_label = max_height, num_frames_total=num_frames_total, load_features=True);
else:
v = self.RegisteredVideo(path=vpath, version_label = max_height, load_features=True);
self.setVersionInfo(version_label=max_height, num_frames_total=v.num_frames_total);
self.save();
return v;
else:
if(get_if_missing):
vpath = self.pullVersion(max_height=max_height, **kwargs);
if(vpath):
num_frames_total = self.getVersionInfo(version_label=max_height, info_label='num_frames_total');
if(num_frames_total):
v = self.RegisteredVideo(path=vpath, version_label = max_height, num_frames_total=num_frames_total, load_features=True);
else:
v = self.RegisteredVideo(path=vpath, version_label=max_height, load_features=True);
self.setVersionInfo(version_label=max_height, num_frames_total=v.num_frames_total);
self.save();
else:
AWARN("COULDNT GET VIDEO FROM {}".format(self.source_location));
else:
AWARN("COULDNT FIND VIDEO LOCALLY");
return;
return v;
def saveFeaturesForVideo(self, video, features_to_save=None, output_dir=None, overwrite=True):
if(features_to_save is None):
return;
if(not isinstance(features_to_save, list)):
features_to_save=[features_to_save];
for f in features_to_save:
self.saveFeatureForVideo(video=video, feature_name=f, output_dir=output_dir, overwrite=overwrite);
def saveFeatureForVideo(self, video, feature_name, output_dir=None, overwrite=True):
if(feature_name=='each'):
return self.saveFeaturesForVideo(video=video, features_to_save=video.getFeaturesList(), output_dir=output_dir, overwrite=overwrite);
version_label = video.getInfo(label='version_label');
source_type = video.getFeatureSourceType(feature_name);
opath = self.getFeaturePath(feature_name=feature_name, version_label=version_label, source_type=source_type, output_dir=output_dir);
make_sure_dir_exists(opath);
if(not os.path.isfile(opath) or overwrite):
if(feature_name=='all'):
video.saveFeatures(path=opath);
return;
else:
vfeature = video.getFeature(name=feature_name, force_recompute=False);
if(vfeature is not None):
video.saveFeature(name=feature_name, path=opath);
def loadFeaturesForVideo(self, video, features_to_load=None):
if(features_to_load is None):
return;
if(not isinstance(features_to_load, list)):
features_to_load=[features_to_load];
for f in features_to_load:
self.loadFeatureForVideo(video=video, feature_name=f);
def loadFeatureForVideo(self, video, feature_name):
if(feature_name=='each'):
return self.loadFeaturesForVideo(video=video, features_to_load=video.getFeatureFunctionsList());
version_label = video.getInfo(label='version_label');
source_type=video.getFeatureSourceType(feature_name);
ipath = self.getFeaturePath(feature_name=feature_name, version_label=version_label, source_type=source_type);
if(os.path.isfile(ipath)):
if(feature_name=='all'):
video.loadFeatures(path=ipath);
else:
video.loadFeature(name=feature_name, path=ipath);
def getFeaturePath(self, feature_name=None, source_type=None, version_label=None, output_dir=None):
assert(feature_name is not None), 'must provide name of feature VideoSource.getFeaturePath'
feature_dir = self.getFeatureDir(feature_name=feature_name, source_type = source_type);
fileext = '.pkl';
if(output_dir is None):
version = self._getVersionLabelDirName(version_label=version_label)+os.sep;
output_dir = pathstring(feature_dir);
outname = self.getName();
if(outname is None):
outname = 'version';
outname = outname+'_'+self._getVersionLabelDirName(version_label=version_label)+fileext;
opath = os.path.join(output_dir, outname);
return opath;
def getFeatureDir(self, feature_name=None, source_type=None):
if(source_type is None):
source_type='video'; # could be 'audio'
# AWARN("getDir('features')= {}\nsource_type= {}\nfeature_name= {}".format(self.getDir('features'), source_type, feature_name))
ftypedir = pathstring(self.getDir('features') + os.sep + source_type + os.sep + feature_name + os.sep);
return ftypedir;
def saveFeaturesForVersion(self, version_label=None, output_dir=None):
assert(output_dir), 'must provide output dir';
v = self.getVersion(max_height=version_label);
v.save(features_to_save='all', output_dir=output_dir);
def RegisteredVideo(self, path=None, version_label=None, version_group = None, num_frames_total=None, load_features = True):
v = self.VideoClass(path=path, name=self.getName()+'_'+self._versionLabelString(version_label=version_label), num_frames_total=num_frames_total);
# v = Video(path=path, name=self.getName()+'_'+self._versionLabelString(version_label=version_label), num_frames_total=num_frames_total);
self.RegisterVideo(video=v, version_label=version_label, load_features=load_features);
return v;
def RegisterVideo(self, video, version_label = None, version_group = None, load_features=True):
def videosave(vidob, features_to_save='all', output_dir=None, overwrite=True):
self.saveFeaturesForVideo(video=vidob, features_to_save=features_to_save, output_dir=output_dir, overwrite=overwrite);
#self.save
def videoload(vidob, features_to_load='all', input_dir=None):
self.loadFeaturesForVideo(video=vidob, features_to_load=features_to_load);
def videoclear(vidob, features_to_clear='all'):
self.removeFeatureFilesForVideo(video=vidob, features_to_remove=features_to_clear);
video.setInfo(label='version_label', value=version_label);
video.setInfo(label='version_group', value=version_group);
video.setInfo(label='video_file_name', value=os.path.split(video.getPath())[1]);
# if(version_group is None):
video.save_func = videosave;
video.load_func = videoload;
video.clear_feature_files_func = videoclear;
video.source=self;
if(load_features is True and hasattr(video, "loadFlowFeatures")):
video.loadFlowFeatures();
elif(load_features is not None and (isinstance(load_features, list) or isinstance(load_features, str))):
video.load(features_to_load = load_features);
# return video;
def addVersion(self, path, version_label=None, version_group=None):
v = self.RegisteredVideo(path=path, version_label=version_label);
video_dict=v.getVersionInfo();
video_dict.update(dict(version_group=version_group));
self.setVersionInfo(video_path = path, version_label=version_label, **video_dict);
self.save();
def addVersionToVideo(self, video, new_video, version_label=None, version_group=None):
version_label = video.getInfo(label='version_label');
video_dict = new_video.getVersionInfo();
if ((version_group is not None) or (video_dict.get('version_group') is None)):
video_dict.update(dict(version_group=version_group));
self.setVersionInfo(video_path=new_video.getPath(), version_label=version_label, **video_dict);
self.save();
def setSource(self, source_location=None, assert_valid=True, **kwargs):
"""
Sets the source of this VideoSource. If file, copies the file to VideoSource directory as "Original" version,
unless copy argument is set to false.
:param source_location: either path to file, or youtube url
:param kwargs: see setSourceYoutube or setSourceFile for options
:return:
"""
if(source_location):
if(os.path.isfile(source_location)):
self.setSourceFile(path = source_location, **kwargs);
else:
self.setSourceYoutube(url=source_location, **kwargs);
return;
elif(kwargs.get('video_path')):
self.setSourceFile(**kwargs);
return;
elif(kwargs.get('url')):
self.setSourceYoutube(**kwargs);
return;
else:
if(assert_valid):
assert(False),'No valid source location provided to setSource.'
def setSourceYoutube(self, url=None, max_height=None, pull_fullres=True, **kwargs):
self.source_location=url;
self.setInfo(label='source_type', value='youtube');
if(pull_fullres):
self.pullYoutubeVideo(max_height=max_height, **kwargs);
self.save();
def setSourceFile(self, path=None, copy=True, **kwargs):
# assert(os.path.isfile(path)), 'Tried to set source but no file exists at {}'.format(path);
if(not os.path.isfile(path)):
return None;
self.video_file_name = os.path.basename(path);
if(not copy):
self.source_location = path;
self.setInfo(label='source_type', value='file_address');
return path;
# output_dir = self.getDir('versions') + os.sep + 'Original' + os.sep;
output_dir = self.getDirForVersion(version_label=None, version_group='Source');
make_sure_dir_exists(output_dir);
output_path = os.path.join(output_dir, self.video_file_name);
# max_height = kwargs.get('max_height');
# if(max_height is not None):
# # print('max_height was {}'.format(max_height));
# original = self.VideoClass(path=path);
# original.writeResolutionCopyFFMPEG(path=output_path, max_height=kwargs.get('max_height'));
# else:
# shutil.copy2(path, output_path);
shutil.copy2(path, output_path);
# self.addVersion(path=output_path, version_label='Original');
self.addVersion(path=output_path, version_label='Full');
self.setInfo(label='source_type', value='file');
self.source_location = output_path;
self.save();
return output_path;
def pullVersion(self, max_height=None, **kwargs):
# assert(self.source_location is not None), "Could not pull version; source location is None."
if(self.source_location is None):
return None;
source_type = self.getInfo('source_type');
if(source_type=='youtube'):
return self.pullYoutubeVideo(max_height=max_height, **kwargs);
else:
return self.pullFileVideo(max_height=max_height, **kwargs)
def pullFileVideo(self, max_height=None, force_recompute=None):
original_path = self.source_location;
assert(os.path.isfile(original_path)), 'SOURCE FILE {} IS MISSING'.format(self.source_location);
original = self.VideoClass(path=original_path);
output_dir = self.getDirForVersion(version_label=max_height, version_group=None);
make_sure_dir_exists(output_dir);
output_path = os.path.join(output_dir, self.video_file_name);
if(max_height is None):
if(os.path.normpath(original_path) != os.path.normpath(output_path)):
shutil.copy2(original_path, output_path);
else:
original.writeResolutionCopyFFMPEG(path=output_path, max_height=max_height);
self.addVersion(path=output_path, version_label=max_height);
return self.getVersionPath(version_label=max_height);
def pullYoutubeVideo(self, max_height=None, write_subtitles=False, save_youtube_info=False,
force_redownload=False):
"""
Downloads video from youtube with height<=max_height. Returns path to downloaded video.
:param max_height: maximum height of video to download
:param write_subtitles: whether to save the subtitles
:param save_youtube_info: whether to save the info json
:param force_redownload: whether to re-download if video exists
:return:
"""
assert (not self.getInfo('source_is_file')), "tried to call pullYoutubeVideo on file source {}.".format(self.getName());
old_vid_path = self.getVersionPath(version_label=max_height);
if ((not force_redownload) and old_vid_path and os.path.isfile(old_vid_path)):
AWARN("Old video version exists with path {}\nSkipping download...\n".format(old_vid_path))
return old_vid_path;
# output_dir = self.getDir('versions') + os.sep + self._getVersionLabelDirName(version_label=max_height) + os.sep;
output_dir = self.getDirForVersion(version_label=max_height, version_group=None);
make_sure_path_exists(output_dir);
if ((not force_redownload) and self.video_file_name is not None):
path_guess = os.path.join(output_dir, self.video_file_name);
if (os.path.isfile(path_guess)):
AWARN("found existing file {}\nSkipping download; set force_redownload=True to overwrite old version.".format(path_guess));
self.addVersion(path=path_guess, version_label=max_height);
return path_guess;
########Download From YouTube#########
vidpath_template = output_dir + '%(title)s-%(id)s' + '.%(ext)s';
ydl_opts = {
'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
'outtmpl': vidpath_template,
}
if (write_subtitles):
ydl_opts['writesubtitles'] = True;
ydl_opts['subtitlesformat'] = '[srt]';
if (max_height):
ydl_opts['format'] = 'bestvideo[height<={}][ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best'.format(
max_height);
ydl_opts['writeinfojson'] = True;
info_dict = None;
AWARN("Downloading {} from {}...".format(self.getName(), self.source_location));
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info_dict = ydl.extract_info(self.source_location, download=True)
# video_source = info_dict.get("source", None)
# video_id = info_dict.get("id", None)
# video_title = info_dict.get('title', None)
usedtitle = info_dict['title'].replace('"', "'").replace('|', '_').replace(':', ' -').replace('/','_').replace('?', '');
usedfilename_withoutext = usedtitle + '-' + info_dict['id'];
usedfilename = usedfilename_withoutext + '.' + info_dict['ext'];
filepath = output_dir + os.sep + usedfilename;
filepathsafe = safe_file_name(filepath);
if (os.path.isfile(filepath)):
os.rename(filepath, filepathsafe);
else:
fpath = glob.glob(output_dir + os.sep + '*' + info_dict['id'] + '.mp4');
assert (len(fpath) == 1), "Wrong number of files for {}\nFound:\n{}".format(filepath, fpath);
os.rename(fpath[0], filepathsafe);
jpath = glob.glob(output_dir + os.sep + '*' + info_dict['id'] + '.info.json');
os.rename(jpath[0], safe_file_name(usedfilename_withoutext + '.info.json'));
print(("Saved to {}".format(filepathsafe)));
self.video_file_name = safe_file_name(usedfilename);
self.title_safe = safe_file_name(usedtitle);
if (save_youtube_info):
self.youtube_info_dict = info_dict;
# v = Video(path=filepathsafe);
# video_dict=v.toDictionary();
# self.setVersionInfo(video_path = filepathsafe, version_label=max_height, num_frames_total=v.num_frames_total, **video_dict);
# self.save();
self.addVersion(path=filepathsafe, version_label=max_height);
return self.getVersionPath(version_label=max_height);
# return youtube_link;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/Video_CV.py
================================================
# from Video import *
from .Image import *
from .Event import *
from .VisualBeat import *
import librosa
FEATURE_FUNCS = {};
VIS_FUNCS = {};
VISVIDEO_FUNCS = {};
FLOW_LOG_EPSILON=1.0;
FLOW_UNIT_GAIN=10000.0;
HISTOGRAM_FRAMES_PER_BEAT = 2;
HISTOGRAM_DOWNSAMPLE_LEVELS = 3;
VB_UPSAMPLE_FACTOR = 1.0;
USING_OPENCV = Image.USING_OPENCV;
if(USING_OPENCV):
##########################################################################
# ################ THESE ARE THE FUNCTIONS TO OVERRIDE! ################ #
# ################ FOR CUSTOM SALIENCY METRICS! ################ #
##########################################################################
# You can modify them here. But I would suggest elsewhere in your code
# just setting Video.localRhythmicSaliencyFunction and
# Video.visualBeatFunction to whatever you want. See how they are assigned
# when Video_CV is included in Video.py. -Abe
def localRhythmicSaliencyFunction(self, **kwargs):
"""
Change to use different function for local saliency
"""
return self.getVisibleImpactEnvelope(**kwargs);
def visualBeatFunction(self, **kwargs):
"""
Change to use different default strategy for selecting visual beats
"""
# beat_params = dict(
# pre_max_time=0.2,
# post_max_time=0.2,
# pre_avg_time=0.2,
# post_avg_time=0.2,
# wait_time=0.1,
# )
beat_params = self._getDefaultPeakPickingTimeParams();
beat_params.update(kwargs);
return self.getVisibleImpacts(**beat_params);
# #################### This is how they are called #################### #
def getLocalRhythmicSaliency(self, force_recompute=False, **kwargs):
feature_name = 'local_rhythmic_saliency';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = dict();
params.update(kwargs);
params.update({'force_recompute':force_recompute});
result = self.localRhythmicSaliencyFunction(**params);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getVisualBeats(self, force_recompute=False, **kwargs):
feature_name = 'visual_beats';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
params.update({'force_recompute': force_recompute});
result = self.visualBeatFunction(**params);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
# ##################################################################### #
##########################################################################
# ###################################################################### #
##########################################################################
def cvGetGrayFrame(self, f):
colorframe = self.getFrame(f).astype(np.uint8);
return ocv.cvtColor(colorframe, ocv.COLOR_RGB2GRAY);
def getImageFromFrameGray(self, f):
frame = self.getImageFromFrame(f);
frame.RGB2Gray();
return frame;
def flow2row(ang, amp, bins, subdivs, n_shifts, density):
h, w = ang.shape[:2];
ncells = np.power(4, subdivs);
nperd = np.power(2, subdivs);
xw = w-n_shifts[1];
yw = h-n_shifts[0];
xcells = np.arange(nperd + 1, dtype=float);
ycells = np.arange(nperd + 1, dtype=float);
xcells = np.floor((xcells / (nperd)) * xw);
ycells = np.floor((ycells / (nperd)) * yw);
# print(n_shifts)
ahis = np.zeros([ncells * bins, n_shifts[0]*n_shifts[1]]);
for dy in range(n_shifts[0]):
for dx in range(n_shifts[1]):
ampwin = amp[dy:dy+yw,dx:dx+xw];
angwin = ang[dy:dy+yw,dx:dx+xw];
cell_counter = 0;
for x in range(nperd):
for y in range(nperd):
ystart=int(ycells[y]);
yend = int(ycells[y+1]);
xstart = int(xcells[x]);
xend = int(xcells[x + 1]);
angcell = angwin[ystart:yend, xstart:xend];
ampcell = ampwin[ystart:yend, xstart:xend];
cahis, cbinbounds = np.histogram(angcell.ravel(), bins=bins, range=(0, 2 * np.pi),
weights=ampcell.ravel(), density=density);
# print("ahis shape: {}\ncahis shape: {}\ndx, dy: {}, {}\ncell_counter: {}\nbins: {}\n".format(ahis.shape, cahis.shape, dx, dy, cell_counter, bins));
ahis[cell_counter * bins:(cell_counter + 1) * bins, dx+dy*n_shifts[0]] = cahis;
cell_counter = cell_counter + 1;
return ahis;
def getFlowFrame(self, frame_index):
prev_frame = self.cvGetGrayFrame(frame_index-1);
this_frame = self.vbGetGrayFrame(frame_index);
return cvDenseFlowFarneback(from_image=prev_frame, to_image=this_frame);
def getFlowFramePolar(self, frame_index):
"""
:param self:
:param frame_index:
:return: polar where polar[:,:,0] is amplitude, and polar[:,:,1] is angle
"""
flow = self.getFlowFrame(frame_index);
fx, fy = flow[:,:,0], flow[:,:,1];
polar = np.zeros(size(flow));
polar[:,:,0] = np.sqrt(fx * fx + fy * fy);
polar[:,:,1] = np.arctan2(fy, fx) + np.pi
return polar;
def computeDirectogramPowers(self, bins=None, dead_zone= 0.05, density=None, save_if_computed=True, noise_floor_percentile=None, **kwargs):
if(bins is None):
bins = 128;
if(noise_floor_percentile is None):
noise_floor_percentile = 20;
print(("Computing Flow Features with deadzone {}".format(dead_zone)))
signal_dim = 128;
m_histvals = np.zeros([signal_dim, self.n_frames(), 3]);
flow_averages = np.zeros([self.n_frames(), 1]);
sampling_rate=self.sampling_rate;
duration = self.getDuration();
nsamples = sampling_rate*duration;
# print(sampling_rate, duration)
frame_start_times = np.linspace(0,duration,num=int(nsamples),endpoint=False);
frame_index_floats = frame_start_times*self.sampling_rate;
lastframe = self.cvGetGrayFrame(frame_index_floats[0]);
start_timer=time.time();
last_timer=start_timer;
fcounter=0;
counter = 0;
for nf in range(len(frame_index_floats)):
nextframe= self.cvGetGrayFrame(frame_index_floats[nf]);
flow = cvDenseFlowFarneback(from_image=lastframe, to_image=nextframe);
h, w = flow.shape[:2];
fx, fy = flow[:,:,0], flow[:,:,1];
# if(filter_median):
# fx = fx-np.median(fx.ravel());
# fy = fy-np.median(fy.ravel());
# assert(False), "SHOULDNT BE FILTERING MEDIAN! VESTIGIAL CODE"
ang = np.arctan2(fy, fx) + np.pi
amp = np.sqrt(fx*fx+fy*fy);
winstarty = int(dead_zone*h);
winendy = h-winstarty;
winstartx = int(dead_zone*w);
winendx = w-winstartx;
angw = ang[winstarty:winendy, winstartx:winendx];
ampw = amp[winstarty:winendy, winstartx:winendx];
mask0 = (ampw>np.percentile(ampw,noise_floor_percentile)).astype(float);
ahis0, cbinbounds = np.histogram(angw.ravel(), bins=bins, range=(0, 2 * np.pi),
weights=mask0.ravel(), density=density);
ahis1, cbinbounds1 = np.histogram(angw.ravel(), bins=bins, range=(0, 2 * np.pi),
weights=ampw.ravel(), density=density);
ahis2, cbinbounds2 = np.histogram(angw.ravel(), bins=bins, range=(0, 2 * np.pi),
weights=np.power(ampw, 2).ravel(), density=density);
m_histvals[:, counter, 0] = ahis0;
m_histvals[:, counter, 1] = ahis1;
m_histvals[:, counter, 2] = ahis2;
lastframe=nextframe;
counter+=1;
fcounter+=1;
if(not (fcounter%50)):
if((time.time()-last_timer)>10):
last_timer=time.time();
print(("{}%% done after {} seconds...".format(100.0*truediv(fcounter,len(frame_index_floats)), last_timer-start_timer)));
params = dict( bins = bins,
deadzone=dead_zone,
density=density);
params.update(kwargs);
self.setFeature(name='directogram_powers', value=m_histvals, params=params);
if(save_if_computed):
self.save(features_to_save=['directogram_powers']);
return m_histvals;
######################### Other Features #############################
def getDirectogramPowers(self, force_recompute=False, **kwargs):
feature_name = 'directogram_powers';
if ((not self.hasFeature(feature_name)) or force_recompute):
flow_powers = self.computeDirectogramPowers(**kwargs);
return self.getFeature(feature_name);
# def getDirectogram(self, bins = None, weights=None, density=None, force_recompute=False, save_if_computed=True, **kwargs):
def getDirectogram(self, **kwargs):
feature_name = 'directogram';
force_recompute = kwargs.get('force_recompute');
if((not self.hasFeature(feature_name)) or force_recompute):
flow_powers = self.getFeature('directogram_powers');
fh = flow_powers[:,:,1];
self.setFeature(name='directogram', value=fh, params=kwargs);
return self.getFeature(feature_name);
def getVisualTempo(self, force_recompute=None, **kwargs):
feature_name = 'visual_tempo';
if ((not self.hasFeature(feature_name)) or force_recompute):
vbe = self.getFeature('local_rhythmic_saliency');
# assert librosa.__version__ == '0.7.1'
# result = librosa.beat.beat_track(onset_envelope=vbe, sr=self.sampling_rate, hop_length=1, **kwargs);
result = librosa.beat.beat_track(onset_envelope=vbe, sr=self.sampling_rate, hop_length=1, **kwargs);
self.setFeature(name=feature_name, value=result, params=kwargs);
return self.getFeature(feature_name);
def getVisualTempogram(self, window_length=None, force_recompute=None, norm_columns = None, **kwargs):
"""
:param self:
:param window_length: in seconds
:param force_recompute:
:param kwargs:
:return:
"""
feature_name = 'visual_tempogram';
if ((not self.hasFeature(feature_name)) or force_recompute):
if(window_length is None):
window_length = DEFAULT_TEMPOGRAM_WINDOW_SECONDS;
params = kwargs;
params.update({'force_recompute': force_recompute});
vbe = self.computeImpactEnvelope(cut_suppression_seconds = None);
onset_envelope = vbe;
win_length = int(round(window_length * self.sampling_rate));
sr = self.sampling_rate;
hop_length = 1;
center=kwargs.get('center');
if(center is None):
center=True;
window='hann'
norm=np.inf;
ac_window = librosa.filters.get_window(window, win_length, fftbins=True)
# Center the autocorrelation windows
n = len(onset_envelope)
if center:
onset_envelope = np.pad(onset_envelope, int(win_length // 2),
mode='linear_ramp', end_values=[0, 0])
# Carve onset envelope into frames
odf_frame = librosa.util.frame(onset_envelope,
frame_length=win_length,
hop_length=hop_length)
# Truncate to the length of the original signal
if center:
odf_frame = odf_frame[:, :n]
odf_frame = librosa.util.normalize(odf_frame,axis=0,norm=norm)
if(norm_columns is None):
norm_columns = True;
if(norm_columns):
# Window, autocorrelate, and normalize
result = librosa.util.normalize(
librosa.core.audio.autocorrelate(odf_frame * ac_window[:, np.newaxis], axis=0), norm=norm, axis=0);
else:
result = librosa.core.audio.autocorrelate(odf_frame * ac_window[:, np.newaxis], axis=0);
result = np.true_divide(result, np.max(result.ravel()));
tempo_bpms = librosa.tempo_frequencies(result.shape[0], hop_length=hop_length, sr=sr)
self.setFeature(name='tempogram_bpms', value=tempo_bpms);
###########
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getVisibleImpactEnvelope(self, force_recompute=False, **kwargs):
feature_name = 'impact_envelope';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result = self.computeImpactEnvelope(forward=True, backward = False, **kwargs);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getForwardVisibleImpactEnvelope(self, force_recompute=False, **kwargs):
"""
Same as getVisibleImpactEnvelope by default.
:param self:
:param force_recompute:
:param kwargs:
:return:
"""
feature_name = 'forward_visual_impact_envelope';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result = self.computeImpactEnvelope(forward=True, backward = False, **kwargs);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getBackwardVisibleImpactEnvelope(self, force_recompute=False, **kwargs):
feature_name = 'backward_visual_impact_envelope';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result = self.computeImpactEnvelope(forward=False, backward = True, **kwargs);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getBothWayVisibleImpactEnvelope(self, force_recompute=False, **kwargs):
feature_name = 'both_way_visual_impact_envelope';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result = self.computeImpactEnvelope(forward=True, backward = True, **kwargs);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getVisibleImpactEnvelopePowers(self, force_recompute=False, **kwargs):
feature_name = 'impact_envelope_powers';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result0 = self.computeImpactEnvelope(power= 0, **params);
result = np.zeros([len(result0), 3]);
result[:, 0] = result0;
result[:, 1] = self.computeImpactEnvelope(power= 1, **params);
result[:, 2] = self.computeImpactEnvelope(power=2, **params);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getCutTimes(self):
return Event.ToStartTimes(self.getCutEvents());
def getCutEvents(self, force_recompute=False, **kwargs):
"""
Hacky estimate of cuts in a video
:param self:
:param force_recompute:
:param kwargs:
:return:
"""
feature_name = 'cut_events';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
powers = self.getFeature('directogram_powers');
im0 = powers[:, :, 0];
im2 = powers[:, :, 2];
imc = np.true_divide(im2, 0.05 + im0);
medsig = np.median(imc, 0);
medall = np.median(imc);
cutsig = np.true_divide(medsig, medall)
cut_detection_ratio = kwargs.get('cut_detection_ratio');
if(cut_detection_ratio is None):
cut_detection_ratio=CUT_DETECTION_RATIO;
clipsig = (cutsig > cut_detection_ratio).astype(float);
clip_floorsig = (cutsig > CUT_DETECTION_FLOOR).astype(float);
clipsig = np.multiply(clipsig, clip_floorsig);
einds = np.flatnonzero(clipsig);
etimes = einds * truediv(1.0, self.sampling_rate);
ev = Event.FromStartTimes(etimes, type='cut');
ev = self.visualBeatsFromEvents(ev);
evout = []
for e in range(len(ev)):
ev[e].setInfo('frame', einds[e]);
result = ev;
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def visualBeatsFromEvents(self, events):
def downsample_hist(sig, levels):
nperbin = np.power(2, levels);
rshp = sig.reshape(-1, nperbin);
return rshp.sum(axis=1);
if(self.hasFeature('impact_envelope')):
svbe=self.getFeature('impact_envelope');
else:
svbe=self.computeImpactEnvelope(cut_suppression_seconds = None);
flow_powers = self.getFeature('directogram_powers');
vis_tempogram = self.getFeature('visual_tempogram');
vbeats = [];
for e in events:
b = VisualBeat.FromEvent(e);
ei = int(round(b.start*self.sampling_rate*VB_UPSAMPLE_FACTOR));
b.weight = svbe[ei];
histsize = int(128/int(np.power(2,HISTOGRAM_DOWNSAMPLE_LEVELS)))
histslice = np.zeros([histsize, HISTOGRAM_FRAMES_PER_BEAT]);
histslice = np.squeeze(np.mean(histslice, 1));
b.flow_histogram = downsample_hist(sig=histslice, levels=HISTOGRAM_DOWNSAMPLE_LEVELS);
b.flow_histogram = np.divide(b.flow_histogram, np.sum(b.flow_histogram));
b.local_autocor = vis_tempogram[:,ei];
b.local_autocor = b.local_autocor/np.max(b.local_autocor);
b.sampling_rate=self.sampling_rate;
vbeats.append(b);
return vbeats;
def getVisualBeatTimes(self, **kwargs):
return Event.ToStartTimes(self.getVisualBeats(**kwargs));
def getDirectionalFlux(self,
f_sigma=None,
median_kernel=None,
power=None,
**kwargs):
"""
The visual impact complement of a spectral flux matrix
:param self:
:param f_sigma: sigma for the gaussian used to filter, using sp.ndimage.filters.gaussian_filter
:param median_kernel: used in sp.signal.medfilt
:param power: Which power of the flow to use. Usually use 1.
:param kwargs:
:return:
"""
def d_x(im):
d_im = np.zeros(im.shape);
d_im[:, 0] = im[:, 0];
for c in range(1, im.shape[1]):
d_im[:, c] = im[:, c] - im[:, c - 1];
return d_im;
if (f_sigma is None):
f_sigma = [5, 3];
if (median_kernel is None):
median_kernel = [3, 3];
if(power is None):
power = 1;
powers = self.getFeature('directogram_powers');
im = powers[:,:,power].copy();
if (f_sigma is not None):
im = sp.ndimage.filters.gaussian_filter(input=im, sigma=f_sigma, order=0);
im = sp.signal.medfilt(im, median_kernel);
return d_x(im);
def computeImpactEnvelope(self,
forward=True,
backward = False,
f_sigma=None,
median_kernel=None,
highpass_window_seconds= 0.8,
cut_percentile=99,
power=None,
crop = None,
normalize = True,
**kwargs):
"""
:param self:
:param forward: include impact going forward in time
:param backward: include impact going backward in time
:param f_sigma: sigma for the gaussian used to filter, using sp.ndimage.filters.gaussian_filter
:param median_kernel: used in sp.signal.medfilt
:param highpass_window_seconds: highpass window size in seconds
:param cut_percentile: percentile above which to consider cuts and to clip
:param power: Which power of the flow to use. Usually use 1.
:param crop:
:param kwargs:
:return:
"""
upsample_factor = kwargs.get('upsample_factor');
inputargs = dict(f_sigma=f_sigma,
median_kernel=median_kernel,
power=power,
crop = crop);
inputargs.update(kwargs);
im_d = self.getDirectionalFlux(**inputargs);
if(forward and backward):
im = np.fabs(im_d);
elif(forward):
im = -im_d;
im = np.clip(im, 0, None)
elif(backward):
im = im_d;
im = np.clip(im, 0, None)
else:
assert(False), "Must be at least one of either forward or backward."
vimpact = np.squeeze(np.mean(im, 0));
sampling_rate = self.sampling_rate;
if(upsample_factor is not None and (upsample_factor>1)):
newlen = upsample_factor * len(vimpact);
sampling_rate = upsample_factor*sampling_rate;
vimpact = sp.signal.resample(vimpact, newlen);
if(highpass_window_seconds):
order = kwargs.get('highpass_order');
if(order is None):
order = 5;
cutoff = truediv(1.0, highpass_window_seconds);
normal_cutoff = cutoff / (sampling_rate*0.5);
b, a = sp.signal.butter(order, normal_cutoff, btype='high', analog=False)
vimpact = sp.signal.filtfilt(b, a, vimpact);
normfactor = np.max(np.fabs(vimpact[:]));
if (cut_percentile is not None):
fx = np.fabs(vimpact);
pv = np.percentile(fx, cut_percentile);
pvlow = np.percentile(fx, cut_percentile-1);
normfactor = pv;
ptile = (vimpact > pv).astype(float);
pntile = (vimpact < -pv).astype(float);
pboth = ptile+pntile;
einds = np.flatnonzero(pboth);
lastind = -2;
for j in range(len(einds)):
if(einds[j]==(lastind+1)):
vimpact[einds[j]]=0;
else:
vimpact[einds[j]]=pvlow;
if(normalize):
vimpact = np.true_divide(vimpact, normfactor);
return vimpact;
# 0.8, cut_suppression_seconds = 0.4,
def computeImpactEnvelopeOld(self, f_sigma=None, median_kernel=None, highpass_window_seconds= 0.8, cut_percentile=99, power=None, crop = None, normalize=None, **kwargs):
"""
I believe this is the version of the function that I used in the original paper. Keeping it around for record.
:param self:
:param f_sigma:
:param median_kernel:
:param highpass_window_seconds:
:param cut_percentile:
:param power:
:param crop:
:param normalize:
:param kwargs:
:return:
"""
def d_x(im):
# d_im = np.zeros(im.shape, dtype=np.float128);
d_im = np.zeros(im.shape);
d_im[:, 0] = im[:, 0];
for c in range(1, im.shape[1]):
d_im[:, c] = im[:, c] - im[:, c - 1];
return d_im;
if (f_sigma is None):
f_sigma = [5, 3];
if (median_kernel is None):
median_kernel = [3, 3];
if(power is None):
power = 1;
upsample_factor = kwargs.get('upsample_factor');
powers = self.getFeature('directogram_powers');
print(("computing impact env with power {}".format(power)));
im = powers[:,:,power].copy();
if (f_sigma is not None):
im = sp.ndimage.filters.gaussian_filter(input=im, sigma=f_sigma, order=0);
im = sp.signal.medfilt(im, median_kernel);
im = -d_x(im);
im = np.clip(im, 0, None)
svbe = np.squeeze(np.mean(im, 0));
sampling_rate = self.sampling_rate;
if(upsample_factor is not None and (upsample_factor>1)):
newlen = upsample_factor * len(svbe);
sampling_rate = upsample_factor*sampling_rate;
svbe = sp.signal.resample(svbe, newlen);
if(highpass_window_seconds):
order = kwargs.get('highpass_order');
if(order is None):
order = 5;
cutoff = truediv(1.0, highpass_window_seconds);
normal_cutoff = cutoff / (sampling_rate*0.5);
b, a = sp.signal.butter(order, normal_cutoff, btype='high', analog=False)
svbe = sp.signal.filtfilt(b, a, svbe);
normfactor = np.max(np.fabs(svbe[:]));
if (cut_percentile is not None):
fx = np.fabs(svbe);
pv = np.percentile(fx, cut_percentile);
pvlow = np.percentile(fx, cut_percentile-1);
normfactor = pv;
ptile = (svbe > pv).astype(float);
pntile = (svbe < -pv).astype(float);
pboth = ptile+pntile;
einds = np.flatnonzero(pboth);
lastind = -2;
for j in range(len(einds)):
if(einds[j]==(lastind+1)):
svbe[einds[j]]=0;
else:
svbe[einds[j]]=pvlow;
if(normalize is not False):
svbe = np.true_divide(svbe, normfactor);
return svbe;
def getVisibleImpacts(self, force_recompute=False, include_cut_events = None, **kwargs):
feature_name = 'visible_impacts';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
svbe = self.getFeature('impact_envelope', **kwargs);
upsample_factor = kwargs.get('upsample_factor');
if(upsample_factor is None):
upsample_factor = 1;
u_sampling_rate = self.sampling_rate*upsample_factor;
peak_params = self._getDefaultPeakPickingTimeParams();
peak_params.update(kwargs); # if params given in arguments, those will override the defaults here.
v_events = Event.FromSignalPeaks(signal=svbe, sampling_rate=u_sampling_rate, **peak_params);
if(include_cut_events):
cut_events = self.getFeature('cut_events');
v_events = v_events + cut_events;
Event.Sort(v_events);
result = self.visualBeatsFromEvents(v_events);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getForwardVisibleImpacts(self, force_recompute=False, include_cut_events = None, **kwargs):
feature_name = 'forward_visual_beats';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
local_saliency = self.getFeature('forward_visual_impact_envelope', **kwargs);
upsample_factor = kwargs.get('upsample_factor');
if(upsample_factor is None):
upsample_factor = 1;
u_sampling_rate = self.sampling_rate*upsample_factor;
v_events = Event.FromSignalPeaks(signal=local_saliency, sampling_rate=u_sampling_rate, event_type= 'forward', **kwargs);
if(include_cut_events):
cut_events = self.getFeature('cut_events');
v_events = v_events + cut_events;
Event.Sort(v_events);
result = Event.SetDirections(v_events, direction=Event.DIRECTION_FORWARD);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getBackwardVisibleImpacts(self, force_recompute=False, include_cut_events = None, **kwargs):
feature_name = 'backward_visual_beats';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
local_saliency = self.getFeature('backward_visual_impact_envelope', **kwargs);
upsample_factor = kwargs.get('upsample_factor');
if(upsample_factor is None):
upsample_factor = 1;
u_sampling_rate = self.sampling_rate*upsample_factor;
v_events = Event.FromSignalPeaks(signal=local_saliency, sampling_rate=u_sampling_rate, **kwargs);
if(include_cut_events):
cut_events = self.getFeature('cut_events');
v_events = v_events + cut_events;
Event.Sort(v_events);
# result = self.visualBeatsFromEvents(v_events);
result = Event.SetDirections(v_events, direction=Event.DIRECTION_BACKWARD);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def findAccidentalDanceSequences(self, target_n_beats = 7, n_samples=25, delta_range = None):
if(delta_range is None):
delta_range = [0.02, 0.5];
deltas = np.linspace(delta_range[0], delta_range[1], num=n_samples, endpoint=True);
deltapick = delta_range[0];
sequences = [];
for i, delta in enumerate(deltas):
peak_vars = self._getDefaultPeakPickingTimeParams(delta=delta);
sequences = self.getVisualBeatSequences(peak_vars=peak_vars, print_summary=False);
# print("Delta {} has top sequence with {} beats".format(delta, len(sequences[0])));
if(len(sequences[0])<=target_n_beats):
deltapick = delta;
break;
print(("Selected delta value {}".format(deltapick)));
return sequences;
def getVisualBeatSequences(self,
search_tempo=None,
target_period=None,
search_window=0.75,
min_beat_limit=None,
max_beat_limit=None,
unary_weight=None,
binary_weight=None,
break_on_cuts=None,
peak_vars=None,
time_range=None,
n_return = None,
unsorted = False,
print_summary = True,
**kwargs):
"""
:param self:
:param search_tempo: optional tempo you would like to find visual beats at
:param target_period: optional target period you would like to use for finding beats. Ignored if search tempo is provided.
:param search_window: longest amount of time (seconds) allowed between beats before a segment is broken into multiple segments
:param min_beat_limit: only consider sequences with
:param unary_weight:
:param binary_weight:
:param break_on_cuts:
:param peak_vars:
:param kwargs:
:return:
"""
if (peak_vars is not None):
# impacts = self.getFeature('visible_impacts', force_recompute=True, **peak_vars);
impacts = self.getVisualBeats(force_recompute = True, **peak_vars);
else:
# impacts = self.getFeature('visible_impacts');
impacts = self.getVisualBeats();
if(time_range is not None):
impactseg = [];
for i in impacts:
if(i.start>time_range[0] and i.start < time_range[1]):
impactseg.append(i);
impacts = impactseg;
if (search_tempo is not None):
tempo = search_tempo;
beat_time = np.true_divide(60.0, tempo);
sequences = VisualBeat.PullOptimalPaths_Basic(impacts, target_period=beat_time, unary_weight=unary_weight,
binary_weight=binary_weight, break_on_cuts=break_on_cuts,
window_size=search_window);
elif(target_period is not None):
sequences = VisualBeat.PullOptimalPaths_Basic(impacts, target_period=target_period, unary_weight=unary_weight,
binary_weight=binary_weight, break_on_cuts=break_on_cuts,
window_size=search_window);
else:
sequences = VisualBeat.PullOptimalPaths_Autocor(impacts, unary_weight=unary_weight, binary_weight=binary_weight,
break_on_cuts=break_on_cuts, window_size=search_window);
r_sequences = [];
if(min_beat_limit is None):
min_beat_limit = 2;
if(max_beat_limit is None):
max_beat_limit = len(impacts)+1;
for S in sequences:
if ((len(S) > min_beat_limit) and (len(S) < max_beat_limit)):
r_sequences.append(S);
if(not unsorted):
r_sequences.sort(key=len, reverse=True);
if(n_return is not None):
r_sequences = r_sequences[:n_return];
if(print_summary):
print(("{} segments".format(len(r_sequences))));
for s in range(len(r_sequences)):
print(("Segment {} has {} beats".format(s, len(r_sequences[s]))));
return r_sequences;
def printVisualBeatSequences(self,
search_tempo=None,
target_period=None,
search_window=None,
min_beat_limit=None,
max_beat_limit=None,
unary_weight=None,
binary_weight=None,
break_on_cuts=None,
peak_vars=None,
n_return = None,
time_range=None, **kwargs):
"""
:param self:
:param target_period:
:param search_tempo:
:param search_window:
:param beat_limit:
:param unary_weight:
:param binary_weight:
:param break_on_cuts:
:param n_return:
:param peak_vars:
:param time_range:
:param kwargs:
:return:
"""
sorted = True;
sequence_args = dict(
search_tempo=search_tempo,
target_period=target_period,
search_window=search_window,
min_beat_limit=min_beat_limit,
max_beat_limit=max_beat_limit,
unary_weight=unary_weight,
binary_weight=binary_weight,
break_on_cuts=break_on_cuts,
peak_vars=peak_vars,
n_return=n_return,
time_range=time_range);
seqs = self.getVisualBeatSequences(**sequence_args)
print(("sequence arguments were:\n{}".format(sequence_args)));
print(("There were {} sequences total".format(len(seqs))));
nclips = 0;
rsegments = [];
for S in seqs:
if (len(S) > 1):
nclips = nclips + 1;
rsegments.append(S);
# rsegments.sort(key=len, reverse=True);
# if (n_return is not None):
# rsegments = rsegments[:n_return];
Event.PlotSignalAndEvents(self.getFeature('impact_envelope'), sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=rsegments[0], time_range=time_range);
return rsegments;
def plotEvents(self, events, time_range = 'default', **kwargs):
time_range_use = time_range;
if(time_range.lower() == 'default'):
time_range_use = [0,0];
time_range_use[0] = events[0].start-1;
time_range_use[1] = events[-1].start+1;
signal = self.getFeature('local_rhythmic_saliency');
mplt = Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate * VB_UPSAMPLE_FACTOR, events=events, time_range=time_range_use, **kwargs);
plt.xlabel('Time (s)')
return mplt;
def plotCutEvents(self, **kwargs):
signal = self.getFeature('impact_envelope');
events = self.getFeature('cut_events', **kwargs);
Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=events, **kwargs);
def plotVisibleImpacts(self, **kwargs):
signal = self.getFeature('impact_envelope');
events = self.getFeature('visible_impacts', **kwargs);
Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=events, **kwargs);
plt.title('Impact Envelope & Visual Beats')
plt.xlabel('Time (s)')
plt.ylabel('Impact Strength')
def plotImpactEnvelope(self, **kwargs):
signal = self.getFeature('local_rhythmic_saliency');
# events = self.getFeature('visual_beats', **kwargs);
events = None;
Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=events, **kwargs);
plt.title('Impact Envelope & Visual Beats')
plt.xlabel('Time (s)')
plt.ylabel('Impact Strength')
def plotVisualBeats(self, **kwargs):
signal = self.getFeature('local_rhythmic_saliency');
events = self.getFeature('visual_beats', **kwargs);
Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=events, **kwargs);
plt.title('Impact Envelope & Visual Beats')
plt.xlabel('Time (s)')
plt.ylabel('Impact Strength')
def loadFlowFeatures(self):
self.load(features_to_load=['directogram_powers', 'directogram']);
FEATURE_FUNCS['local_rhythmic_saliency'] = getLocalRhythmicSaliency;
FEATURE_FUNCS['directogram_powers'] = getDirectogramPowers;
FEATURE_FUNCS['directogram'] = getDirectogram;
FEATURE_FUNCS['impact_envelope'] = getVisibleImpactEnvelope;
FEATURE_FUNCS['impact_envelope_powers'] = getVisibleImpactEnvelopePowers;
FEATURE_FUNCS['visible_impacts'] = getVisibleImpacts;
FEATURE_FUNCS['visual_beats'] = getVisualBeats;
# FEATURE_FUNCS['backward_visual_beats'] = getBackwardVisualBeats;
# FEATURE_FUNCS['forward_visual_beats'] = getForwardVisualBeats;
FEATURE_FUNCS['backward_visual_impact_envelope'] = getBackwardVisibleImpactEnvelope;
FEATURE_FUNCS['both_way_visual_impact_envelope'] = getBothWayVisibleImpactEnvelope;
FEATURE_FUNCS['forward_visual_impact_envelope'] = getForwardVisibleImpactEnvelope;
FEATURE_FUNCS['directional_flux'] = getDirectionalFlux;
FEATURE_FUNCS['visual_tempogram'] = getVisualTempogram;
FEATURE_FUNCS['cut_events']=getCutEvents;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/VisBeatDefines.py
================================================
VB_DEBUG = True;
DEFAULT_TEMPOGRAM_WINDOW_SECONDS = 5;
AUDIO_DEFAULT_HOP_LENGTH = 512;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/VisBeatExampleVideo.py
================================================
import os
from visbeat3.SourceLocationParser import ParseSourseLocation
class VisBeatExampleVideo(object):
def __init__(self, name, url, start_beat=None, end_beat = None, display_name = None, code=None, leadin=None, **kwargs):
self.name = name;
self.url = url;
self.start_beat = start_beat;
self.end_beat = end_beat;
self._display_name = display_name;
self._code = code;
self.leadin = leadin;
for k in kwargs:
setattr(self, k, kwargs[k]);
if(code is None):
sloc = ParseSourseLocation(self.url);
self._code = sloc.code;
#
@property
def code(self):
return self._getCode();
def _getCode(self):
return self._code;
@code.setter
def code(self, value):
self._setCode(value);
def _setCode(self, value):
self._code = value;
#
# def _ytEmbedCode(self):
#
@property
def display_name(self):
return self._getDisplayName();
def _getDisplayName(self):
if(self._display_name is None):
return self.name;
else:
return self._display_name;
#
def _ytWatchURL(self):
return 'https://www.youtube.com/watch?v={}'.format(self.code);
def _ytEmbedURL(self, autoplay=None):
s = 'https://www.youtube.com/embed/{}'.format(self.code);
if(autoplay):
s = s+'?autoplay=1';
return s;
def _ytThumbURL(self):
return 'https://ytimg.googleusercontent.com/vi/{}/default.jpg'.format(self.code);
def _fancyBoxCode(self, with_label = None):
""""""
s = HTMLCode();
if(with_label):
s.addLine("")
s.addLine('
'.format(watchurl=self._ytWatchURL(),
alt_name = self.display_name,
thumburl = self._ytThumbURL()))
if(with_label):
s.addLine('');
# s.addLine('{displayname}'.format(self.url, self.display_name));
s.addLine('{displayname}'.format(displayname=self.display_name));
s.addLine(' ')
s.addLine(' ');
return s.string;
from bs4 import BeautifulSoup
class HTMLCode(object):
def __init__(self, start_string=None):
self._code = "";
self._lines = [];
if(start_string is not None):
self.add(start_string)
self._soup = None;
#
@property
def string(self):
return self._getString();
def _getString(self):
return BeautifulSoup(self.code).prettify();
#
@property
def code(self):
return self._getCode();
def _getCode(self):
return self._code;
@code.setter
def code(self, value):
self._setCode(value);
def _setCode(self, value):
self._code = value;
#
#
@property
def soup(self):
return self._getSoup();
def _getSoup(self):
if(self._soup is None):
self._makeSoup();
return self._soup;
def _makeSoup(self):
self._soup = BeautifulSoup(self.code, 'html.parser');
# @soup.setter
# def soup(self, value):
# self._setSoup(value);
# def _setSoup(self, value):
# self._soup = value;
#
def add(self, s):
self.code = self.code+s;
def addLine(self, s):
self.code = self.code+'\n'+s;
def startTable(self, id=None, class_ = None, **kwargs):
targs = dict(table_width="80%", border=1, cellspacing=1, cellpadding=1)
targs.update(kwargs);
s = ''.format(**targs);
self.addLine(s);
self.addLine('');
def endTable(self):
self.addLine("");
self.addLine("
");
def startRow(self):
self.addLine('');
def endRow(self):
self.addLine(' ');
def addColumnLabel(self, label):
self.addLine('')
self.addLine(label);
self.addLine(' ');
def addRowLabel(self, label):
self.addLine('')
self.addLine(label);
self.addLine(' ');
def addRowCell(self, content):
self.addLine("");
self.addLine("")
self.addLine(content);
self.addLine("")
self.addLine(" ");
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/VisBeatImports.py
================================================
from .VisBeatDefines import *
from .AImports import *
from .AObject import AObject
import numpy as np
import scipy as sp
import os
import imageio
import matplotlib
try:
import matplotlib.pyplot as plt
except ImportError as e:
AWARN("matplotlib problem... if you are using conda try installing with 'conda install matplotlib'")
matplotlib.use('agg');
import matplotlib.pyplot as plt
import matplotlib.style as ms
import io
import base64
import math
from operator import truediv
import time
import shutil
from time import gmtime, strftime, localtime
import librosa;
from ._mediafiles import GetVBMarkPath
def local_time_string():
return strftime("%Y-%m-%d_%H:%M:%S", localtime());
def VBWARN(message):
print(message)
#
# def send_warnings_to_print_red(message, category, filename, lineno):
# print(colored('{} WARNING! file: {} Line:{}\n{}'.format(category, filename, lineno, message), 'red'))
# old_showwarning = warnings.showwarning
# warnings.showwarning = send_warnings_to_print_red;
VB_MACHINE_ID = None;
# if(VB_MACHINE_ID):
# matplotlib.use('PS');
ISNOTEBOOK = False;
if(runningInNotebook()):
ISNOTEBOOK = True;
import IPython;
import IPython.display
ms.use('seaborn-muted')
if(not runningInSpyder()):
get_ipython().magic('matplotlib inline')
from IPython.lib import kernel
connection_file_path = kernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]
# print("Kernel ID:\n{}".format(kernel_id));
from IPython.display import HTML
VBIPY = IPython;
#%matplotlib inline
# else:
# matplotlib.use('PS');
def vb_get_ipython():
return VBIPY;
def clipping_params(clip_bins=30, clip_fraction=0.95):
return dict(clip_bins=clip_bins, clip_fraction=clip_fraction);
def get_hist_clipped(signal, clip_bins=30, clip_fraction=0.95):
holdshape = signal.shape[:];
sigrav = signal.copy().ravel();
sigh, sigb = np.histogram(sigrav, bins=clip_bins);
maxbini=np.argmax(sigh);
totalmass = np.sum(sigh);
total_included = truediv(sigh[maxbini],totalmass);
prevbini = maxbini;
nextbini=maxbini;
bins_included = 1;
icounter=0;
while(total_included=0 and sigh[prevbini]==0) and (nextbini<(clip_bins) and sigh[nextbini]==0)):
prevbini=prevbini-1;
nextbini=nextbini+1;
else:
if((prevbini>=0 and sigh[prevbini]>0) or nextbini>=clip_bins):
prevbini=prevbini-1;
if((nextbini<(clip_bins) and sigh[nextbini]>0) or prevbini<0):
nextbini=nextbini+1;
included_segment=sigh[max(prevbini,0):min(nextbini+1, clip_bins)];
total_included = truediv(np.sum(included_segment), totalmass);
bins_included=len(included_segment);
icounter+=1;
clipsig = np.clip(a=sigrav, a_min=sigb[max(prevbini,0)], a_max=sigb[min(nextbini,clip_bins)]);
clipsig.shape=signal.shape
return clipsig;
def np_scale_to_range(data, value_range=None):
if(value_range is None):
value_range = [0.0,255.0];
d = data.copy().ravel();
currentmin=np.min(d);
currentmax=np.max(d);
currentscale = currentmax-currentmin;
if(currentscale==0):
VBWARN("CANNOT SCALE CONSTANT ARRAY TO RANGE")
return;
divscale = truediv(1.0,currentscale);
newrange=(value_range[1]-value_range[0]);
d = (d*divscale)*newrange;
newmin = (currentmin*divscale)*newrange;
d = d-newmin+value_range[0]
d.shape=data.shape;
return d
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/VisualBeat.py
================================================
from .Event import *
class VisualBeat(Event):
def VBOBJECT_TYPE(self):
return 'VisualBeat';
def __init__(self, start=None, type=None, weight=None, index=None, unrolled_start = None, direction=0):
Event.__init__(self, start=start, type=type, weight=weight, index=index, unrolled_start=unrolled_start, direction=direction);
def initializeBlank(self):
Event.initializeBlank(self);
self.flow_histogram = None;
self.local_autocor = None;
self.sampling_rate = None;
def __str__(self):
return "start:{}\ntype:{}\nweight:{}\nindex:{}\nunrolled_start:{}\nis_active:{}\n".format(self.start, self.type, self.weight, self.index, self.unrolled_start, self.is_active);
# def toGUIDict(self, is_active=1):
# return dict(start=self.start, index=self.index, is_active=None)
def toDictionary(self):
d=Event.toDictionary(self);
# d['start']=self.start;
# d['type']=self.type;
# d['weight']=self.weight;
# d['index']=self.index;
# d['unrolled_start']=self.unrolled_start;
d['flow_histogram']=self.flow_histogram;
d['local_autocor']=self.local_autocor;
d['sampling_rate']=self.sampling_rate;
return d;
def initFromDictionary(self, d):
Event.initFromDictionary(self, d);
self.start = d['start'];
self.type = d['type'];
self.weight = d['weight'];
self.index = d['index'];
self.unrolled_start = d['unrolled_start'];
self.flow_histogram = d.get('flow_histogram');
self.local_autocor = d.get('local_autocor');
self.sampling_rate = d.get('sampling_rate');
def clone(self, start=None):
if(start):
newv = VisualBeat(start = start, type=self.type, weight=self.weight, index=self.index);
else:
newv = VisualBeat(start = self.start, type=self.type, weight=self.weight, index=self.index);
newv.flow_histogram = self.flow_histogram.copy();
newv.local_autocor = self.local_autocor.copy();
newv.sampling_rate = self.sampling_rate;
return newv;
@staticmethod
def FromEvent(e):
if(isinstance(e,VisualBeat)):
return e.clone();
else:
return VisualBeat(start=e.start, type=e.type, weight=e.weight, index=e.index);
@staticmethod
def time_window_func(max_separation, break_on_cuts=None):
def window_func(a, b):
if(break_on_cuts and (a.type=='cut' or b.type=='cut')):
return False;
if(np.fabs(a.start-b.start)3.75):
score=-1;
return binary_weight*score;
return objective_func;
@staticmethod
def angle_binary_objective(binary_weight=None, absolute=None):
if (binary_weight is None):
binary_weight = 1.0;
# if (angle_weight is None):
# angle_weight = 0.0;
def objective_func(a, b):
# T = np.fabs(a.start - b.start);
# tempo_score = -np.power(np.log(truediv(T, target_period)), 2.0) * binary_weight;
# should mask out unary contribution from orthogonal angles
if(absolute):
return binary_weight * (np.fabs(np.dot(a.flow_histogram, b.flow_histogram)) - 0.70710678118); # cos 45 degrees
else:
return binary_weight * (np.dot(a.flow_histogram, b.flow_histogram)); # cos 45 degrees
return objective_func;
@staticmethod
def Double(events, type=None):
doubled = [];
for e in range(1, len(events)):
halfstart = 0.5 * (events[e].start + events[e - 1].start);
newhevent = events[e].clone(start=halfstart);
if(type is not None):
newhevent.type = type;
doubled.append(newhevent);
doubled.append(events[e]);
return doubled;
@staticmethod
def weight_unary_objective(unary_weight=None):
if(unary_weight is None):
unary_weight = 1.0;
def getweight_func(b):
return unary_weight*b.weight;
return getweight_func;
@staticmethod
def PullOptimalPaths_Basic(vis_beats, target_period, unary_weight=None, binary_weight=None, window_size=None, break_on_cuts = None):
if(window_size is None):
window_size = DEFAULT_WINDOW_FACTOR*target_period;
binary_objective = VisualBeat.tempo_binary_objective(target_period=target_period, binary_weight = binary_weight);
unary_objective = VisualBeat.weight_unary_objective(unary_weight=unary_weight);
window_function = VisualBeat.time_window_func(max_separation = window_size, break_on_cuts=break_on_cuts);
return VisualBeat.DynamicProgramOptimalPaths(vis_beats=vis_beats,
unary_objective_func=unary_objective,
binary_objective_func=binary_objective,
window_func=window_function);
@staticmethod
def PullOptimalPaths(vis_beats, unary_fn=None, binary_fn=None, window_fn=None, target_period=None, unary_weight=None, binary_weight=None, window_size=None,
break_on_cuts=None):
if (window_size is None):
window_size = DEFAULT_WINDOW_FACTOR * target_period;
if(binary_fn == 'autocor'):
binary_objective = VisualBeat.autocor_binary_objective(binary_weight=binary_weight);
elif(binary_fn == 'angle'):
binary_objective = VisualBeat.angle_binary_objective(binary_weight=binary_weight);
else:
binary_objective = VisualBeat.tempo_binary_objective(target_period=target_period, binary_weight=binary_weight);
unary_objective = VisualBeat.weight_unary_objective(unary_weight=unary_weight);
window_function = VisualBeat.time_window_func(max_separation=window_size, break_on_cuts=break_on_cuts);
return VisualBeat.DynamicProgramOptimalPaths(vis_beats=vis_beats,
unary_objective_func=unary_objective,
binary_objective_func=binary_objective,
window_func=window_function);
@staticmethod
def PullOptimalPaths_Autocor(vis_beats, unary_weight=None, binary_weight=None, window_size=None,
break_on_cuts=None, **kwargs):
if (window_size is None):
# assert(False), 'no window size provided'
# window_size = DEFAULT_WINDOW_FACTOR * target_period;
window_size = 200;
AWARN('NO WINDOWSIZE PROVIDED! PullOptimalPaths_Autocor');
binary_objective = VisualBeat.autocor_binary_objective(binary_weight=binary_weight);
unary_objective = VisualBeat.weight_unary_objective(unary_weight=unary_weight);
window_function = VisualBeat.time_window_func(max_separation=window_size, break_on_cuts=break_on_cuts);
return VisualBeat.DynamicProgramOptimalPaths(vis_beats=vis_beats,
unary_objective_func=unary_objective,
binary_objective_func=binary_objective,
window_func=window_function);
@staticmethod
def DynamicProgramOptimalPaths(vis_beats, unary_objective_func, binary_objective_func, window_func):
class Node(object):
def __init__(self, object, prev_node=None):
self.object = object;
self.prev_node = prev_node;
self.cum_score=None;
nodes = [];
beats = Event.GetSorted(vis_beats);
Event.ApplyIndices(beats);
for b in beats:
nodes.append(Node(object=b));
nodes[0].prev_node = None;
nodes[0].cum_score = unary_objective_func(nodes[0].object);
current_segment = [];
segments = [];
for n in range(1,len(nodes)):
current_node = nodes[n];
current_segment.append(current_node);
options = [];
j = n-1;
while(j>=0 and window_func(current_node.object,nodes[j].object)):
options.append(nodes[j]);
j = j-1;
if(len(options)==0):
current_node.prev_node=None;
current_node.cum_score=unary_objective_func(current_node.object);
segments.append(current_segment);
current_segment = [];
else:
best_choice = options[0];
best_score = options[0].cum_score+binary_objective_func(current_node.object, best_choice.object);
for o in range(1,len(options)):
score = options[o].cum_score+binary_objective_func(current_node.object, options[o].object);
if(score>best_score):
best_choice=options[o];
best_score=score;
current_node.prev_node = best_choice;
current_node.cum_score = best_score+unary_objective_func(current_node.object);
if(len(current_segment)>0):
segments.append(current_segment);
sequences = [];
for S in segments:
seq = [];
max_node = S[0];
max_score = max_node.cum_score;
for n in range(len(S)):
if(S[n].cum_score>max_score):
max_node = S[n];
max_score = max_node.cum_score;
trace_node = max_node;
while(trace_node.prev_node is not None):
seq.append(trace_node.object);
trace_node=trace_node.prev_node;
seq.reverse();
sequences.append(seq);
return sequences;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/Warp.py
================================================
from .VisBeatImports import *
from .EventList import *
import math
DEFAULT_LEAD_TIME = 0;
DEFAULT_TAIL_TIME = 0;
class Warp(AObject):
"""Warp (class): defines how one time signal should be warped to another. Given primarily as source/target events to be matched.
Attributes:
source_events: source events
target_events: target events
"""
def VBOBJECT_TYPE(self):
return 'Warp';
def __init__(self, path=None):
AObject.__init__(self, path=path);
if(path):
self.loadFile();
@staticmethod
def FromEvents(source_events, target_events):
w = Warp();
sevents = source_events;
if(isinstance(source_events, EventList)):
sevents = source_events.events;
tevents = target_events;
if(isinstance(target_events, EventList)):
tevents = target_events.events;
w.source_events=sevents;
w.target_events=tevents;
# w.repeatShorterEvents();
return w
@staticmethod
def FromEventLists(source_eventlist, target_eventlist):
w = Warp();
w.source_events = source_eventlist.events;
w.target_events = target_eventlist.events;
# w.repeatShorterEvents();
return w
def initializeBlank(self):
AObject.initializeBlank(self);
self.source_events = [];
self.target_events = [];
# self.a_info['WarpType'] = 'Linear';
self.warp_func = None; # Warp.LinearInterp;
# self.warp_func_st = None;
# self.warp_func_ts = None;
def getTargetStart(self, lead=None):
target_start = self.target_events[0].getStartTime();
if (lead is None):
lead = min(target_start, DEFAULT_LEAD_TIME);
return target_start - lead;
def getTargetEnd(self, lead=None):
lastind = min(len(self.source_events), len(self.target_events)) - 1;
return self.target_events[lastind].getStartTime() + DEFAULT_TAIL_TIME;
def getSourceStart(self):
source_start = self.source_events[0].getUnrolledStartTime();
return source_start;
def getSourceEnd(self):
lastind = min(len(self.source_events), len(self.target_events)) - 1;
return self.source_events[lastind].getUnrolledStartTime();
def getWarpedSourceStart(self, lead=None):
source_start = self.source_events[0].getUnrolledStartTime();
if (lead is None):
lead = min(source_start, DEFAULT_LEAD_TIME);
return self.warpSourceTime(source_start - lead);
def getWarpedSourceEnd(self, tail=None):
last_event = min(len(self.source_events), len(self.target_events)) - 1;
source_end = self.source_events[last_event].getUnrolledStartTime();
if (tail is None):
tail = DEFAULT_TAIL_TIME;
source_end = source_end + tail;
return self.warpSourceTime(source_end);
def setWarpFunc(self, warp_type, **kwargs):
if (warp_type == 'square'):
self.warp_func = [Warp.SquareInterp, Warp.SquareInterp];
elif (warp_type == 'linear'):
self.warp_func = [Warp.LinearInterp, Warp.LinearInterp];
elif (warp_type == 'cubic'):
self.warp_func = [Warp.CubicInterp, Warp.CubicInterp];
elif (warp_type == 'quad'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events, Warp.WFunc_Quadratic(), **kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events, Warp.WFunc_Quadratic(), **kwargs)];
elif (warp_type == 'mouth'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events, Warp.WFunc_Mouth(**kwargs), **kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events, Warp.WFunc_Mouth(**kwargs), **kwargs)];
elif (warp_type == 'weight'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events,
Warp.WFunc_Weight(use_to_weights=None, **kwargs), **kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events,
Warp.WFunc_Weight(use_to_weights=True, **kwargs), **kwargs)];
elif (warp_type == 'half_accel'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events, Warp.WFunc_P(p=0.5),
**kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events, Warp.WFunc_P(p=0.5),
**kwargs)];
elif (warp_type == 'p'):
p = kwargs.get('p');
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events, Warp.WFunc_P(p=p),
**kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events, Warp.WFunc_P(p=p),
**kwargs)];
elif (warp_type == 'target_time_source_fraction'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events,
Warp.WFunc_targettime_sourcefraction(**kwargs),
**kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events,
Warp.WFunc_targettime_sourcefraction(**kwargs),
**kwargs)];
elif (warp_type == 'target_source_fractions'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events,
Warp.WFunc_target_source_fractions(**kwargs),
**kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events,
Warp.WFunc_target_source_fractions(**kwargs),
**kwargs)];
elif (warp_type is not None):
self.warp_func = [warp_type, warp_type];
self.setInfo('WarpType', warp_type);
return;
def warpSourceTime(self, t):
return self.warp_func[0](t, a_events=self.source_events, b_events=self.target_events);
def warpSourceTimes(self, t):
tw = t.copy();
for a in range(len(t)):
tw[a] = self.warpSourceTime(t[a]);
return tw;
def warpTargetTime(self, t):
return self.warp_func[1](t, a_events=self.target_events, b_events=self.source_events);
def warpTargetTimes(self, t):
tw = t.copy();
for a in range(len(t)):
tw[a] = self.warpTargetTime(t[a]);
return tw;
def plot(self, xlim=None, sampling_rate=None, new_figure=None, render_control_points=True, render_labels=True,
time_range=None, full_source_range=None, **kwargs):
if (sampling_rate is None):
sampling_rate = 30;
source_duration = self.getSourceEnd() - self.getSourceStart();
old_frame_time = truediv(1.0, sampling_rate);
target_start = self.getTargetStart();
target_end = self.getTargetEnd();
# if(xlim is not None):
# target_start=xlim[0]
target_duration = target_end - target_start;
new_n_samples = target_duration * sampling_rate;
target_start_times = np.linspace(target_start, target_end, num=new_n_samples, endpoint=False);
unwarped_target_times = [];
for st in target_start_times:
unwarped_target_times.append(self.warpTargetTime(st));
if (new_figure):
fig = plt.figure();
unwarped_target_times = np.array(unwarped_target_times);
# unwarped_target_times = unwarped_target_times-unwarped_target_times[0]+target_start;
plt.plot(target_start_times, unwarped_target_times, '-');
if (render_control_points):
lastind = min(len(self.source_events), len(self.target_events)) - 1;
targeteventtimes = Event.ToStartTimes(self.target_events[:lastind]);
sourceeventtimes = Event.ToStartTimes(self.source_events[:lastind]);
plt.plot(targeteventtimes, sourceeventtimes, 'o', label='Control Points');
if (xlim is not None):
xrng = [xlim[0] + target_start, xlim[1] + target_start];
ylim = [self.warpTargetTime(xrng[0]), self.warpTargetTime(xrng[1])];
plt.xlim(xrng);
plt.ylim(ylim);
if (time_range is not None):
plt.xlim(time_range);
if (render_labels):
plt.ylabel('Source Time');
plt.xlabel('Target Time');
plt.title('Warp Curve')
if (new_figure is not None):
return fig;
def plotImage(self, xlim=None, sampling_rate=None):
if (sampling_rate is None):
sampling_rate = 30;
target_start = self.getTargetStart();
target_end = self.getTargetEnd() + 10;
target_duration = target_end - target_start;
new_n_samples = target_duration * sampling_rate;
target_start_times = np.linspace(target_start, target_end, num=new_n_samples, endpoint=True);
unwarped_target_times = [];
for st in target_start_times:
unwarped_target_times.append(self.warpTargetTime(st));
unwarped_target_times = np.array(unwarped_target_times);
pim = Image.PlotImage(signal=unwarped_target_times, show_axis=True, xvals=target_start_times,
sampling_rate=sampling_rate, events=self.target_events, xlime=[0, 100], ylims=[0, 110]);
return pim;
def repeatShorterEvents(self, endpoints=False):
n_events = max(len(self.source_events), len(self.target_events));
self.source_events = Event.RepeatToLength(self.source_events, n=n_events, endpoints=endpoints);
self.target_events = Event.RepeatToLength(self.target_events, n=n_events, endpoints=endpoints);
@staticmethod
def FromEvents(source_events, target_events):
w = Warp();
w.source_events = source_events;
w.target_events = target_events;
# w.repeatShorterEvents();
return w
@staticmethod
def LinearInterp(t, a_events, b_events):
n_events = min(len(a_events), len(b_events));
next_a_event_index = n_events;
for s in range(n_events):
if (t < a_events[s].start):
next_a_event_index = s;
break;
prev_a_event_time = 0;
prev_b_event_time = 0;
if (next_a_event_index > 0):
prev_a_event_time = a_events[next_a_event_index - 1].start;
prev_b_event_time = b_events[next_a_event_index - 1].start;
next_a_event_time = a_events[n_events - 1].start;
next_b_event_time = b_events[n_events - 1].start;
if (next_a_event_index < n_events):
next_a_event_time = a_events[next_a_event_index].start;
next_b_event_time = b_events[next_a_event_index].start;
a_event_gap = next_a_event_time - prev_a_event_time;
# b_event_gap = next_b_event_time - prev_b_event_time;
t_progress = t - prev_a_event_time;
# take care of past-the-end case, by simply letting time proceed normally past the last event
if (a_event_gap == 0):
return prev_b_event_time + t_progress;
next_weight = t_progress / (1.0 * a_event_gap);
return (next_weight * next_b_event_time) + ((1.0 - next_weight) * prev_b_event_time);
# additional_points = [];
# for i in range(-10, 11):
# additional_points.append([0.1 * i, 0.51])
@staticmethod
def plotWarpMethodTest(warp_type, additional_points=None, **kwargs):
sev = [];
tev = [];
pts = [[1.0, 1.0],
[-1.0, 1.0],
[0.5, 1.0],
[1.0, 0.5],
[-1.0, 0.5],
[0.5, 0.5],
[1.0, 0.3],
[-1.0, 0.3],
[0.5, 0.3]];
if (additional_points is not None):
pts = pts + additional_points;
currentt = [0.0, 0.0];
sev.append(Event(start=0.0));
tev.append(Event(start=0.0));
for p in pts:
currentt[0] = currentt[0] + p[0];
currentt[1] = currentt[1] + p[1];
sev.append(Event(start=currentt[0]));
tev.append(Event(start=currentt[1]));
# warp_type = 'target_time_source_fraction';
# other_params['acceleration_target_time'] = 0.5;
# other_params['acceleration_source_fraction'] = 0.75;
warpf = Warp.FromEvents(sev, tev);
warpf.setWarpFunc(warp_type, **kwargs);
warpf.plot()
@staticmethod
def SquareInterp(t, a_events, b_events):
n_events = min(len(a_events), len(b_events));
next_a_event_index = n_events;
for s in range(n_events):
if (t < a_events[s].start):
next_a_event_index = s;
break;
prev_a_event_time = 0;
prev_b_event_time = 0;
if (next_a_event_index > 0):
prev_a_event_time = a_events[next_a_event_index - 1].start;
prev_b_event_time = b_events[next_a_event_index - 1].start;
next_a_event_time = a_events[n_events - 1].start;
next_b_event_time = b_events[n_events - 1].start;
if (next_a_event_index < n_events):
next_a_event_time = a_events[next_a_event_index].start;
next_b_event_time = b_events[next_a_event_index].start;
a_event_gap = next_a_event_time - prev_a_event_time;
# b_event_gap = next_b_event_time - prev_b_event_time;
t_progress = t - prev_a_event_time;
# take care of past-the-end case, by simply letting time proceed normally past the last event
if (a_event_gap == 0):
return prev_b_event_time + t_progress;
progress_frac = t_progress / (1.0 * a_event_gap);
next_weight = math.pow(progress_frac, 2);
# accel = 3;
# bweight = math.pow(progress_frac,accel);
# aweight = math.pow(1.0-progress_frac,accel);
# sumweight = aweight+bweight;
# next_weight=bweight/sumweight;
return (next_weight * next_b_event_time) + ((1.0 - next_weight) * prev_b_event_time);
@staticmethod
def GetEventWarpFunc(from_events, to_events, f, lead_time=None, **kwargs):
start_cap_time = min(from_events[0].start, to_events[0].start);
if (lead_time is not None):
start_cap_time = min(start_cap_time, lead_time);
n_events = min(len(from_events), len(to_events));
# f_events = Event.GetUnrolledList(from_events[:n_events], assert_on_folds=True);
f_events = Event.GetUnrolledList(from_events[:n_events]);
t_events = Event.GetUnrolledList(to_events[:n_events]);
def rfunc(t, **kwargs):
next_f_event_index = n_events - 1;
for e in range(n_events):
if (t < f_events[e].unrolled_start):
next_f_event_index = e;
break;
if (next_f_event_index == 0):
from_cap_event = Event(start=f_events[0].start - start_cap_time, weight=0, type='startcap');
to_cap_event = Event(start=t_events[0].start - start_cap_time, weight=0, type='startcap')
return f(t, f_neighbors=[from_cap_event, f_events[0]], t_neighbors=[to_cap_event, t_events[0]]);
else:
return f(t,
f_neighbors=[f_events[next_f_event_index - 1], f_events[next_f_event_index]],
t_neighbors=[t_events[next_f_event_index - 1], t_events[next_f_event_index]]);
return rfunc;
@staticmethod
def WFunc_Quadratic():
def rfunc(t, f_neighbors, t_neighbors, **kwargs):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
next_weight = math.pow(progress_frac, 2);
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_Weight(use_to_weights=None, **kwargs):
print("USING WEIGHT-BASED WARP");
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
if (use_to_weights):
weight = t_neighbors[1].weight;
else:
weight = f_neighbors[1].weight;
p = 1.0 - weight;
# a = truediv(1.0, (1.0+p*p-2*p)); # if a=b
a = 1.0 - np.power((1.0 - p), 2.0); # b=1
if (progress_frac < p):
next_weight = a * progress_frac;
else:
next_weight = (a * progress_frac) + np.power((progress_frac - p), 2.0);
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_P(p=None, **kwargs):
if (p is None):
p = 0.5;
print(("USING P WARP with P={}".format(p)));
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
# a = truediv(1.0, (1.0+p*p-2*p)); # if a=b
a = 1.0 - np.power((1.0 - p), 2.0); # b=1
if (progress_frac < p):
next_weight = a * progress_frac;
else:
next_weight = (a * progress_frac) + np.power((progress_frac - p), 2.0);
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_Mouth(p_acceleration_time=0.1, **kwargs):
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
if (f_neighbors[1].type == 'mouth_open' or t_neighbors[1].type == 'mouth_open'):
p = 1.0 - truediv(p_acceleration_time, to_event_gap);
if (p < 0):
next_weight = math.pow(progress_frac, 2);
else:
# a = truediv(1.0, (1.0+p*p-2*p)); # if a=b
a = 1.0 - np.power((1.0 - p), 2.0); # b=1
if (progress_frac < p):
next_weight = a * progress_frac;
else:
next_weight = (a * progress_frac) + np.power((progress_frac - p), 2.0);
else:
next_weight = progress_frac;
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_targettime_sourcefraction(acceleration_target_time=0.1, acceleration_source_fraction=0.8, **kwargs):
"""
This assumes that you are mapping from the target to the source, as is the most common use case.
:param acceleration_target_time: amount of from time to spend accelerating
:param acceleration_source_fraction: fraction of source to accelerate through
:return:
"""
lin_source_fraction = 1.0 - acceleration_source_fraction;
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return to_times[
0] + t_progress; # is this right? doesnt seem to come up, not sure what behavior should be looking back on it...
progress_frac = truediv(t_progress, from_event_gap);
time_left = from_event_gap - t_progress;
p = 1.0 - truediv(acceleration_target_time, from_event_gap);
p2 = p * p;
q = 1.0 - acceleration_source_fraction;
if (acceleration_target_time >= from_event_gap or q > (p2)):
next_weight = math.pow(progress_frac, 2);
elif (time_left >= acceleration_target_time):
lin_t_progress_frac = truediv(t_progress, from_event_gap - acceleration_target_time);
next_weight = lin_t_progress_frac * lin_source_fraction;
else:
pdnom = (p2 - 2.0 * p + 1.0)
# I just used matlab to symbolic inverse matrix of equations, then simplified by hand
a = ((1.0 - q) / pdnom) + (q / (p * (p - 1)));
b = ((2 * p * (q - 1)) / pdnom) - ((q * (p + 1)) / (p2 - p))
# c = ((p2 - (q * (2 * p - 1))) / pdnom) + (q / (p - 1));
c = 1 - a - b;
next_weight = a * progress_frac * progress_frac + b * progress_frac + c;
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_target_source_fractions(acceleration_target_fraction=0.8, acceleration_source_fraction=0.9, **kwargs):
"""
This assumes that you are mapping from the target to the source, as is the most common use case.
:param acceleration_target_fraction: fraction of target to spend accelerating
:param acceleration_source_fraction: fraction of source to accelerate through
:return:
"""
lin_source_fraction = 1.0 - acceleration_source_fraction;
def rfunc(t, f_neighbors, t_neighbors):
print(acceleration_target_fraction)
print(acceleration_source_fraction)
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return to_times[
0] + t_progress; # is this right? doesnt seem to come up, not sure what behavior should be looking back on it...
progress_frac = truediv(t_progress, from_event_gap);
time_left = from_event_gap - t_progress;
p = 1.0 - acceleration_target_fraction;
p2 = p * p;
q = 1.0 - acceleration_source_fraction;
if (acceleration_target_fraction >= 1 or q > (p2)):
next_weight = math.pow(progress_frac, 2);
elif (progress_frac <= p):
lin_t_progress_frac = truediv(t_progress, p * from_event_gap);
next_weight = lin_t_progress_frac * lin_source_fraction;
else:
pdnom = (p2 - 2.0 * p + 1.0)
# I just used matlab to symbolic inverse matrix of equations, then simplified by hand
a = ((1.0 - q) / pdnom) + (q / (p * (p - 1)));
b = ((2 * p * (q - 1)) / pdnom) - ((q * (p + 1)) / (p2 - p))
# c = ((p2 - (q * (2 * p - 1))) / pdnom) + (q / (p - 1));
c = 1 - a - b;
next_weight = a * progress_frac * progress_frac + b * progress_frac + c;
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_AB(const_factor, quad_factor, **kwargs):
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
next_weight = math.pow(progress_frac, 2);
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
@staticmethod
def ABWarp():
next_from_event_time = from_events[n_events - 1].start;
next_to_event_time = to_events[n_events - 1].start;
if (next_from_event_index < n_events):
next_from_event_time = from_events[next_from_event_index].start;
next_to_event_time = to_events[next_to_event_index].start;
from_event_gap = next_from_event_time - prev_from_event_time;
# b_event_gap = next_b_event_time - prev_b_event_time;
t_progress = t - prev_from_event_time;
# take care of past-the-end case, by simply letting time proceed normally past the last event
if (from_event_gap == 0):
return prev_to_event_time + t_progress;
progress_frac = t_progress / (1.0 * from_event_gap);
next_weight = math.pow(progress_frac, 2);
return (next_weight * next_to_event_time) + ((1.0 - next_weight) * prev_to_event_time);
@staticmethod
def CubicInterp(t, a_events, b_events):
# def CubicInterp(a_events, b_events, t):
f = Warp.CubicInterpFunc(a_events=a_events, b_events=b_events);
return f(t);
@staticmethod
def LinearInterpFunc(a_events, b_events):
if (a_events[0].start > 0):
ae = np.concatenate((np.asarray([0]), Event.ToStartTimes(a_events)));
else:
ae = Event.ToStartTimes(a_events);
be = Event.ToStartTimes(b_events);
if (len(be) > len(ae)):
be = be[:len(ae)];
elif (len(ae) > len(be)):
ae = ae[:len(be)];
return sp.interpolate.interp1d(ae, be, 'linear', bounds_error=False, fill_value='extrapolate');
@staticmethod
def CubicInterpFunc(a_events, b_events):
event_times = Event.ToStartTimes(a_events);
wevent_times = Event.ToStartTimes(b_events);
minlen = min(len(event_times), len(wevent_times));
event_times = event_times[:minlen];
wevent_times = wevent_times[:minlen];
splinecap = np.arange(0, 1, 0.25);
spline_times = np.concatenate((splinecap + event_times[0] - 1, event_times));
wspline_times = np.concatenate((splinecap + wevent_times[0] - 1, wevent_times));
spline_times = np.append(spline_times, splinecap + 0.5 + spline_times[-1]);
wspline_times = np.append(wspline_times, splinecap + 0.5 + wspline_times[-1]);
# get spline to translate initial times to warped times
splineX = sp.interpolate.interp1d(spline_times, wspline_times, kind='cubic', bounds_error=False,
fill_value='extrapolate');
return splineX;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/__init__.py
================================================
from .VisBeatImports import *
from .Video import *
from .VideoClip import *
from .VideoSource import *
from .VisBeatExampleVideo import VisBeatExampleVideo
import re
import os;
import shutil
from .SourceLocationParser import ParseSourseLocation
VISBEAT_ASSETS_DIR = './VisBeatAssets/';
from . import fileui
fileui.INITIAL_DIR = VISBEAT_ASSETS_DIR;
def SetAssetsDir(assets_dir):
global VISBEAT_ASSETS_DIR;
VISBEAT_ASSETS_DIR = assets_dir;
make_sure_dir_exists(assets_dir);
AINFORM("VISBEAT_ASSETS_DIR set to {}".format(VISBEAT_ASSETS_DIR));
make_sure_dir_exists(GetVideoSourcesDir());
temp_dir = os.path.join(VISBEAT_ASSETS_DIR, 'TEMP_FILES'+os.sep);
make_sure_dir_exists(temp_dir);
Video.VIDEO_TEMP_DIR = temp_dir;
fileui.INITIAL_DIR = VISBEAT_ASSETS_DIR;
def GetAssetsDir():
return VISBEAT_ASSETS_DIR;
def GetVideoSourcesDir():
video_sources_dir = os.path.join(GetAssetsDir(), 'VideoSources'+os.sep);
make_sure_dir_exists(video_sources_dir);
return video_sources_dir;
def PullVideo(name=None, source_location=None, max_height=240, **kwargs):
if(isinstance(name, VisBeatExampleVideo)):
assert(source_location is None), 'Provided VisBeatExampleVideo and source location? What are you trying to do?';
source_location = name.url;
vname = name.name;
elif(name is None):
assert(source_location is not None), "Must provide an argument to pullvideo";
sloc = ParseSourseLocation(source_location);
vname =sloc.code;
else:
vname = name;
vs = GetVideoSource(vname);
if(vs and vs.source_location==source_location):
v = vs.getVersion(max_height=max_height);
v.load(features_to_load = 'all');
return v;
print("destination:", GetVideoSourcesDir(), "name:", vname, "source_location:", source_location)
vs = VideoSource.NewVideoSource(destination=GetVideoSourcesDir(), name=vname, source_location=source_location, max_height=max_height, **kwargs);
v = vs.getVersion(max_height=max_height);
return v;
def ClipVideo(video, time_range, max_height=240):
video_fullres = video.source.getVersion();
vclip = video_fullres.VideoClip(start=time_range[0], end=time_range[1]);
vcdir = video.source.getDirForVersion(version_label='{}_{}'.format(str(time_range[0]), str(time_range[1])), version_group='Clips');
make_sure_dir_exists(vcdir);
vcname = video.getName() + 'clip_{}_{}'.format(str(time_range[0]), str(time_range[1]));
vcpath = os.path.join(vcdir, vcname+'.mp4');
vclip.write(output_path=vcpath);
vs = VideoSource.NewVideoSource(destination=GetVideoSourcesDir(), name=vcname, source_location=vcpath);
return vs.getVersion(max_height=max_height);
def GetVideoSource(name):
vname = name;
if (isinstance(name, VisBeatExampleVideo)):
vname = name.name;
path = os.path.join(GetVideoSourcesDir(), vname) + os.sep;
if (os.path.isdir(path)):
return VideoSource(path=path);
def LoadVideo(name, max_height=240):
vname = name;
if (isinstance(name, VisBeatExampleVideo)):
vname = name.name;
path = os.path.join(GetVideoSourcesDir(), vname)+os.sep;
if(os.path.isdir(path)):
vs = VideoSource(path=path);
v = vs.getVersion(max_height=max_height);
v.load(features_to_load = 'all');
return v;
else:
return None;
def Dancefer(source_video, target,
synch_video_beat=0, synch_audio_beat=0,
beat_offset = 0, leadin = None, nbeats=None,
source_harmonic = None, target_harmonic = None, source_harmonic_offset=None, target_harmonic_offset=None,
force_recompute=None, warp_type = 'quad',
name_tag=None, name_tag_prefix=None, output_path = None,
**kwargs):
"""
:param source_video: video to warp
:param target: music to warp to
:param synch_video_beat: integer specifying a beat (as in the nth beat) from the video to synchronize with synch_audio_beat
:param synch_audio_beat: integer specifying a beat (as in the nth beat) from the video to synchronize with synch_video_beat
:param beat_offset: Lets you offset which beats you want to render. This is mostly for testing different parts of an output.
:param leadin: how many beats before the synch beats to render
:param nbeats: lets you restrict output to rendering n beats
:param source_harmonic: can be None, 'half', or 'double'. 'half' will use every other beat, which you can offset with source_harmonic_offset. 'double' will add an additional beat between every consecutive beat. update - added 'third' for waltzes.
:param target_harmonic: can be None, 'half', or 'double'. 'half' will use every other beat, which you can offset with source_harmonic_offset. 'double' will add an additional beat between every consecutive beat. update - added 'third' for waltzes.
:param source_harmonic_offset: optional offset for harmonic
:param target_harmonic_offset: optional offset for harmonic
:param force_recompute:
:param warp_type:
:param name_tag:
:param name_tag_prefix:
:param output_path:
:param kwargs:
:return:
"""
if((output_path is not None) and (not force_recompute)):
if(os.path.exists(output_path)):
return Video(output_path);
if(isinstance(target, Video)):
target_audio = target.getAudio();
else:
target_audio = target;
synchaudio = synch_audio_beat;
synchvideo = synch_video_beat;
lead_in = leadin;
if(lead_in is None):
lead_in = min(synchaudio, synchvideo);
elif(isinstance(lead_in, str) and lead_in[0]=='<'):
# lead_in = min(synchaudio, synchvideo, int(lead_in));
lead_in = min(synchaudio, int(lead_in));
start_audio_beat = synchaudio-lead_in;
start_video_beat = synchvideo-lead_in;
if(beat_offset and beat_offset>0):
start_audio_beat = start_audio_beat+beat_offset;
start_video_beat = start_video_beat+beat_offset;
print(("Warping {} to {}".format(source_video.getName(), target_audio.getName())));
bitrate = None;
vbeats = source_video.audio.getBeatEvents()
tbeats = target_audio.getBeatEvents()
if(start_video_beat < 0):
if(synchvideo == 0):
vbeats = [vbeats[0].clone()]+vbeats;
vbeats[0].start = vbeats[0].start-(vbeats[2].start-vbeats[1].start);
vbadd = Event.SubdivideIntervals(vbeats[:2], -start_video_beat);
vbeats = vbadd+vbeats[2:];
start_video_beat = 0;
vbeats = vbeats[start_video_beat:];
tbeats = tbeats[start_audio_beat:];
if(source_harmonic=='half'):
vbeats = Event.Half(vbeats, source_harmonic_offset);
elif (source_harmonic == 'third'):
vbeats = Event.Third(vbeats, source_harmonic_offset);
elif(source_harmonic == 'double'):
vbeats = Event.Double(vbeats);
if (target_harmonic == 'half'):
tbeats = Event.Half(tbeats, target_harmonic_offset);
elif (target_harmonic == 'third'):
tbeats = Event.Third(tbeats, target_harmonic_offset);
elif (target_harmonic == 'double'):
tbeats = Event.Double(tbeats);
if(nbeats):
print(("Rendering {} beats of result".format(nbeats)))
if(len(vbeats)>nbeats):
vbeats = vbeats[:nbeats];
print((len(vbeats)))
if(len(tbeats)>nbeats):
tbeats = tbeats[:nbeats];
print((len(tbeats)))
else:
if(vbeats[-1].start0):
start_audio_beat = start_audio_beat+beat_offset;
start_video_beat = start_video_beat+beat_offset;
print(("Warping {} to {}".format(source_video.getName(), target_audio.getName())));
bitrate = None;
vbeats = source_beats;
if(source_beats is None):
vbeats = source_video.getVisualBeats();
tbeats = target_beats;
if(target_beats is None):
tbeats = target_audio.getBeatEvents();
if(start_video_beat < 0):
if(synchvideo == 0):
vbeats = [vbeats[0].clone()]+vbeats;
vbeats[0].start = vbeats[0].start-(vbeats[2].start-vbeats[1].start);
vbadd = Event.SubdivideIntervals(vbeats[:2], -start_video_beat);
vbeats = vbadd+vbeats[2:];
start_video_beat = 0;
vbeats = vbeats[start_video_beat:];
tbeats = tbeats[start_audio_beat:];
if (source_harmonic == 'half'):
vbeats = Event.Half(vbeats, source_harmonic_offset);
elif (source_harmonic == 'third'):
vbeats = Event.Third(vbeats, source_harmonic_offset);
elif (source_harmonic == 'double'):
vbeats = Event.Double(vbeats);
if (target_harmonic == 'half'):
tbeats = Event.Half(tbeats, target_harmonic_offset);
elif (target_harmonic == 'third'):
tbeats = Event.Third(tbeats, target_harmonic_offset);
elif (target_harmonic == 'double'):
tbeats = Event.Double(tbeats);
if(nbeats):
print(("Rendering {} beats of result".format(nbeats)))
if(len(vbeats)>nbeats):
vbeats = vbeats[:nbeats];
print((len(vbeats)))
if(unfold_to_n):
vbeats = Event.UnfoldToN(vbeats, unfold_to_n, momentum=momentum);
if (len(tbeats) > len(vbeats)):
tbeats = tbeats[:len(vbeats)];
if(warp_type is 'weight'):
vbeats = source_video.visualBeatsFromEvents(vbeats);
if(name_tag is None):
name_tag = warp_type+'_sab_'+str(start_audio_beat)+'_svb_'+str(start_video_beat);
if(name_tag_prefix is not None):
name_tag = name_tag+name_tag_prefix;
warp_args = dict(target=target_audio,
source_events=vbeats,
target_events = tbeats,
warp_type=warp_type,
force_recompute=force_recompute,
name_tag = name_tag)
if(bitrate):
warp_args.update(dict(bitrate=bitrate));
warp_args.update(kwargs);
warped_result = source_video.getWarped(**warp_args);
if(output_path):
final_output_path = output_path;
if(os.path.isfile(final_output_path)):
output_filename = os.path.basename(output_path);
name_parts = os.path.splitext(output_filename);
output_filename_base = name_parts[0];
output_directory_path = os.path.dirname(output_path);
if (output_directory_path == ''):
output_directory_path = '.'
output_ext = name_parts[1];
ntry = 1;
tryname = output_filename_base+ '_' + str(ntry);
while (os.path.isfile(os.path.join(output_directory_path, tryname+output_ext)) and ntry<100):
ntry = ntry+1;
tryname = output_filename_base + '_' + str(ntry);
final_output_path = os.path.join(output_directory_path, tryname + output_ext);
shutil.copy2(src=warped_result.getPath(), dst=final_output_path);
n_frames_total = warped_result.num_frames_total;
warp_used = warped_result.getInfo('warp_used');
warped_result_final = Video(path = final_output_path, num_frames_total=n_frames_total);
warped_result_final.setInfo(label='warp_used', value=warp_used);
os.remove(warped_result.getPath())
warped_result = warped_result_final;
return warped_result;
def getVBSegments(self,source_video,
source_beats = None,
search_tempo=None,
search_window=None,
max_height=None,
beat_limit=None,
n_return=None,
unary_weight=None,
binary_weight=None,
break_on_cuts=None,
peak_vars=None):
source = source_video;
if(source_beats is None):
if (peak_vars is not None):
vbeats = source.getFeature('simple_visual_beats', **peak_vars);
else:
vbeats = source.getFeature('simple_visual_beats');
else:
vbeats = source_beats;
#
if (search_tempo is not None):
tempo = search_tempo;
beat_time = np.true_divide(60.0, tempo);
clips = VisualBeat.PullOptimalPaths_Basic(vbeats, target_period=beat_time, unary_weight=unary_weight,
binary_weight=binary_weight, break_on_cuts=break_on_cuts,
window_size=search_window);
else:
clips = VisualBeat.PullOptimalPaths_Autocor(vbeats, unary_weight=unary_weight, binary_weight=binary_weight,
break_on_cuts=break_on_cuts, window_size=search_window);
if (beat_limit is None):
beat_limit = 2;
print(("There were {} candidates".format(len(vbeats))));
nclips = 0;
segments = [];
for S in clips:
if (len(S) > beat_limit):
nclips = nclips + 1;
segments.append(S);
if (n_return is not None):
segments.sort(key=len, reverse=True);
segments = segments[:n_return];
return segments;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/_dancefer_examples.py
================================================
from .VisBeatExampleVideo import *
from ._music_examples import *
# dances = [];
dances.append(VisBeatExampleVideo(display_name = 'SNSD: HAHAHA', name='snsd_hahaha', url='https://www.youtube.com/watch?v=OxNsx0eMsGU', start_beat=42));
dances.append(VisBeatExampleVideo(display_name = 'Boston Dynamics: Spot the Dancing Robot', name='spot_the_dancing_robot', url='https://www.youtube.com/watch?v=kHBcVlqpvZ8', start_beat = 9));
dances.append(VisBeatExampleVideo(display_name = 'Michael Jackson: Thriller', name = 'thriller', url = 'https://www.youtube.com/watch?v=wlHUJbl-t7o', start_beat = 4))
dances.append(VisBeatExampleVideo(display_name = 'LMFAO: Party Rock Anthem',name='party_rock', url='https://www.youtube.com/watch?v=WZRMpC_wh0M', start_beat=4, leadin=4))
dances.append(VisBeatExampleVideo(display_name = 'BTS: Boy in Luv', name='boy_in_luv', url='https://www.youtube.com/watch?v=gqz6Adx63w8', start_beat=34));
dances.append(VisBeatExampleVideo(display_name = 'Thays Monaro: Redneck Woman',name='gwilson_redneck_woman', url='https://www.youtube.com/watch?v=1apy8YPygKo', start_beat=65))
dances.append(VisBeatExampleVideo(display_name = 'Music Express: Dancing in the Street', name='dance_cc_dancing_in_the_street', url='https://www.youtube.com/watch?v=fzZ2CoL3IMQ', start_beat=3));
dances.append(VisBeatExampleVideo(display_name = 'Barney and Friends: Mr. Golden Sun',name='barney_mr_golden_sun', url='https://www.youtube.com/watch?v=ya4yyg9XiI4', start_beat=24))
dances.append(VisBeatExampleVideo(display_name = 'M. Express: Friends Forever', name='dance_cc_friends_forever', url='https://www.youtube.com/watch?v=T6ZX6wkJ5Ns', start_beat=2));
dances.append(VisBeatExampleVideo(display_name = 'Just Dance Kids: Gummy Bear',name='jdk_gummy_bear', url='https://www.youtube.com/watch?v=KVE-T2_vLpY', start_beat=60))
dances.append(VisBeatExampleVideo(display_name = 'M. Express: Feelin Good',name='dance_cc_feelin_good', url='https://www.youtube.com/watch?v=uBWp9rr6w08', start_beat=49));
# dances.append(VisBeatExampleVideo(display_name = 'Kiesza: Hideaway', name='hideaway', url='https://www.youtube.com/watch?v=Vnoz5uBEWOA', start_beat=124))
dances.append(VisBeatExampleVideo(display_name = 'SNSD: Genie', name='snsd_genie', url='https://www.youtube.com/watch?v=6SwiSpudKWI', start_beat=141));
dances.append(VisBeatExampleVideo(display_name = 'Momoland Boom Boom', name='momoland_boom_boom', url='https://www.youtube.com/watch?v=0HKfjsM2hSw', start_beat = 145));#33#
dances.append(VisBeatExampleVideo(display_name = 'Snap: Rhythm is a Dancer', name='rhythm_is_a_dancer', url='https://www.youtube.com/watch?v=fDWFVI8PQOI', start_beat=65));
dances.append(VisBeatExampleVideo(display_name = 'Janet Jackson: Rhythm Nation', name='rhythm_nation', url='https://www.youtube.com/watch?v=OAwaNWGLM0c', start_beat = 226));
dances.append(VisBeatExampleVideo(display_name = 'BTS Just One Day', name='bts_just_one_day', url='https://www.youtube.com/watch?v=KQeAg45p2UI', start_beat=200));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/_dancify_examples.py
================================================
from .VisBeatExampleVideo import *
from ._music_examples import *
dances.append(VisBeatExampleVideo(display_name = 'Turtle', name='turtle', url='https://www.youtube.com/watch?v=PWD4gktEUAY', start_beat=0));
dances.append(VisBeatExampleVideo(display_name = 'Louie The Cat', name='louie_the_cat', url='https://www.youtube.com/watch?v=hqFG6d86ygI', start_beat=None));
accidental_dances = [];
accidental_dances.append(VisBeatExampleVideo(display_name="Trump IACP Full", name="trump_iacp_full", url='https://www.youtube.com/watch?v=pu4dPTi6SEg', target_n_beats = 7))
accidental_dances.append(VisBeatExampleVideo(display_name="Trump Tax Reform WH.gov Full", name="trump_taxreform_remarks_1", url="https://www.youtube.com/watch?v=zB-lhTEQdKY"))
# accidental_dances.append(VisBeatExampleVideo(display_name="", name="", url=""))
synth = [];
synth.append(VisBeatExampleVideo(name='synth_ball_metronome_w_noise', url = 'https://youtu.be/-mqJIGdro6A', start_beat = None));
synth.append(VisBeatExampleVideo(name='synth_test_ball_1', url = 'https://youtu.be/SjXsMYBJEF8', start_beat = None));
synth.append(VisBeatExampleVideo(name='synth_test_ball_1_gt_impact_sounds', url = 'https://youtu.be/tsdsQm4iTNg', start_beat = None));
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/_mediafiles.py
================================================
import os
VB_MEDIA_UTILS_PATH = os.path.abspath(__file__)
VB_MEDIA_UTILS_DIR = os.path.abspath(os.path.dirname(__file__));
MEDIAFILES_DIR = os.path.join(VB_MEDIA_UTILS_DIR, 'assets'+os.sep)
AUDIO_FILES_DIR = os.path.join(MEDIAFILES_DIR, 'audio'+os.sep);
AUDIO_FILES = [];
AUDIO_FILE_PATHS = {};
for filename in os.listdir(AUDIO_FILES_DIR):
# if(reduce(lambda x,y: x or y, map(lambda ext: filename.lower().endswith(ext), Audio.MEDIA_FILE_EXTENSIONS()))):
AUDIO_FILES.append(filename);
AUDIO_FILE_PATHS[filename]=(os.path.join(AUDIO_FILES_DIR, filename));
def GetTestAudioPath(filename):
return AUDIO_FILE_PATHS[filename];
VIDEO_FILES_DIR = os.path.join(MEDIAFILES_DIR, 'video'+os.sep);
VIDEO_FILES = [];
VIDEO_FILE_PATHS = [];
if(os.path.exists(VIDEO_FILES_DIR)):
for filename in os.listdir(VIDEO_FILES_DIR):
VIDEO_FILES.append(filename);
VIDEO_FILE_PATHS.append(os.path.join(VIDEO_FILES_DIR, filename));
IMAGE_FILES_DIR = os.path.join(MEDIAFILES_DIR, 'images'+os.sep);
IMAGE_FILES = [];
IMAGE_FILE_PATHS = {};
for filename in os.listdir(IMAGE_FILES_DIR):
IMAGE_FILES.append(filename);
IMAGE_FILE_PATHS[filename] = (os.path.join(IMAGE_FILES_DIR, filename));
def GetTestImagePath(filename=None):
if(filename is None):
filename = "VisBeatWatermark.png"
return IMAGE_FILE_PATHS[filename];
def GetVBMarkPath():
return IMAGE_FILE_PATHS["VisBeatWatermark.png"];
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/_music_examples.py
================================================
from .VisBeatExampleVideo import *
dances = [];
music = [];
music.append(VisBeatExampleVideo(display_name = 'U Cant Touch This', name='cant_touch_this', url='https://www.youtube.com/watch?v=_NNYI8VbFyY', start_beat=2, leadin=2));
music.append(VisBeatExampleVideo(display_name = 'Mary Poppins: Supercalifrag.', name='supercalifrag', url='https://www.youtube.com/watch?v=rihNRTTcztQ', start_beat = 5, leadin = 3));
music.append(VisBeatExampleVideo(display_name = 'Migos: Walk It Talk It',name='walkit_talkit', url='https://www.youtube.com/watch?v=fGqdIPer-ms', start_beat = 134));
music.append(VisBeatExampleVideo(display_name = 'Rammstein: Du Hast',name='du_hast', url = 'https://www.youtube.com/watch?v=W3q8Od5qJio', start_beat = 193));
music.append(VisBeatExampleVideo(display_name = 'Taylor Swift: Shake It Off', name='shake_it_off', url='https://www.youtube.com/watch?v=nfWlot6h_JM', start_beat=112));
music.append(VisBeatExampleVideo(display_name = 'Michael Jackson: Billie Jean', name='billie_jean', url='https://www.youtube.com/watch?v=Zi_XLOBDo_Y', start_beat=169));
music.append(VisBeatExampleVideo(display_name = 'Hall and Oates: You Make My Dreams', name='you_make_my_dreams', url='https://www.youtube.com/watch?v=EErSKhC0CZs', start_beat=95));
music.append(VisBeatExampleVideo(display_name = 'Parry Gripp: Breakfast Burrito',name="breakfast_burrito", url='https://www.youtube.com/watch?v=prPjpwsGiws', start_beat=32))
music.append(VisBeatExampleVideo(display_name = 'Pharrell Williams: Happy',name='happy', url='https://www.youtube.com/watch?v=y6Sxv-sUYtM', start_beat=69, leadin=3))
music.append(VisBeatExampleVideo(display_name = 'Aqua: Barbie Girl',name='barbie_girl', url='https://www.youtube.com/watch?v=ZyhrYis509A', start_beat=67, leadin=4));
music.append(VisBeatExampleVideo(display_name = 'Jhameel: Montage',name='music_cc_jhameel_montage', url='https://www.youtube.com/watch?v=vYr_nCmsgoE', start_beat=103))
music.append(VisBeatExampleVideo(display_name = 'Vengaboys: We like to Party',name='we_like_to_party', url='https://www.youtube.com/watch?v=6Zbi0XmGtMw', start_beat=65))
music.append(VisBeatExampleVideo(display_name = 'Rick Astley: Never Gonna Give You Up', name='rick_roll', url='https://www.youtube.com/watch?v=dQw4w9WgXcQ', start_beat = 3, leadin=3));
music.append(VisBeatExampleVideo(display_name = 'Mark Ronson: Uptown Funk ft. Bruno Mars', name='uptown_funk', url='https://www.youtube.com/watch?v=OPf0YbXqDm0', start_beat=32));
music.append(VisBeatExampleVideo(display_name = 'Missy Elliot: Work It', name='work_it', url='https://www.youtube.com/watch?v=cjIvu7e6Wq8', start_beat=52, leadin = 1));
music.append(VisBeatExampleVideo(display_name = 'If I only had a brain', name='only_had_a_brain', url='https://www.youtube.com/watch?v=nauLgZISozs', start_beat=14));
music.append(VisBeatExampleVideo(display_name = 'Kane Brown: Lose It', name='kb_lose_it', url='https://www.youtube.com/watch?v=Z8nkc2KKjd8', start_beat=56));
# music.append(VisBeatExampleVideo(display_name = 'Check Meowt', name='pg_check_meowt', url='https://youtu.be/NjKYX4bQpf0', start_beat = 16));
# music.append(VisBeatExampleVideo(display_name = 'Wu-Tang Clan: Protect Ya Neck', name='wutang_protect_ya_neck', url='https://www.youtube.com/watch?v=R0IUR4gkPIE', start_beat = None));
# music.append(VisBeatExampleVideo(display_name = 'Ice Cube: It Was A Good Day',name='it_was_a_good_day', url='https://www.youtube.com/watch?v=h4UqMyldS7Q', start_beat=64, harmonic = 'half'));
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/command_line.py
================================================
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/fileui/__init__.py
================================================
from sys import platform
if platform == "linux" or platform == "linux2":
PLATFORM = 'linux';
elif platform == "darwin":
PLATFORM = 'osx';
elif platform == "win32":
PLATFORM = 'windows'
SUPPORTED = False;
INITIAL_DIR ='./';
if(PLATFORM == 'osx'):
from . import uipath
def GetFilePath(initial_path=None):
if(initial_path is None):
return uipath.uiGetFilePath(initial_path=INITIAL_DIR);
else:
return uipath.uiGetFilePath(initial_path);
def GetDirectory(initial_path=None):
if(initial_path is None):
return uipath.uiGetDirectory(initial_path=INITIAL_DIR);
else:
return uipath.uiGetDirectory(initial_path);
def GetSaveFilePath(initial_path=None, file_extension = None):
if(initial_path is None):
return uipath.uiGetSaveFilePath(initial_path=INITIAL_DIR, file_extension=file_extension);
else:
return uipath.uiGetSaveFilePath(initial_path=initial_path, file_extension=file_extension);
def Show(path):
uipath.showInFinder(path);
def Open(path):
uipath.openOSX(path);
SUPPORTED = True;
else:
def GetFilePath(initial_path=None):
return None;
def GetDirectory(initial_path=None):
return None;
def GetSaveFilePath(initial_path=None, file_extension = None):
return None;
def Show(path):
return None;
def Open(path):
return None;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/fileui/uipath.py
================================================
import os
import subprocess
def uiGetFilePath(initial_path=None):
try:
if(initial_path):
output = subprocess.check_output("osascript -e 'set strPath to POSIX file \"{}\"' -e 'set theDocument to choose file with prompt \"Please select a document to process:\" default location strPath' -e 'set theDocument to (the POSIX path of theDocument)'".format(initial_path), shell=True)
else:
output = subprocess.check_output("osascript -e 'set theDocument to choose file with prompt \"Please select a document to process:\"' -e 'set theDocument to (the POSIX path of theDocument)'", shell=True)
return output.replace('\n', '');
except subprocess.CalledProcessError as e:
print((e.output));
# assert(False)
# grabpath = get_ipython().run_cell_magic(u'bash', u'', "osascript -e 'set theDocument to choose file with prompt \"Please select a document to process:\"' -e 'set theDocument to (the POSIX path of theDocument)'>&2")
def uiGetDirectory(initial_path=None):
try:
if(initial_path):
output = subprocess.check_output("osascript -e 'set strPath to POSIX file \"{}\"' -e 'set thedir to choose folder with prompt \"Please select a file:\" default location strPath' -e 'set thedir to (the POSIX path of thedir)'".format(initial_path), shell=True)
else:
output = subprocess.check_output("osascript -e 'set thedir to choose folder with prompt \"Please select a directory:\"' -e 'set thedir to (the POSIX path of thedir)'", shell=True)
return output.replace('\n', '');
except subprocess.CalledProcessError as e:
print((e.output));
# assert(False)
def uiGetSaveFilePath(initial_path=None, file_extension=None):
try:
osastr = "osascript ";
if(initial_path):
osastr = osastr+"-e 'set strPath to POSIX file \"{}\"' ".format(initial_path);
osastr = osastr+"-e 'set theDocument to choose file name with prompt \"Save As File:\" ";
if(initial_path):
osastr = osastr+"default location strPath";
osastr = osastr+"' ";
osastr = osastr+"-e 'set theDocument to (the POSIX path of theDocument)'"
output = subprocess.check_output(osastr, shell=True);
ostring = output.replace('\n', '');
if (file_extension is not None):
if (not ostring.endswith(file_extension)):
ostring = ostring + file_extension;
return ostring;
except subprocess.CalledProcessError as e:
AWARN('ERROR')
print((e.output));
def showInFinder(path):
return openOSX(get_dir_from_path(path));
def openOSX(path):
return subprocess.check_output("open {}".format(put_string_in_quotes(path)), shell=True);
def put_string_in_quotes(s):
return "\""+s+"\""
def get_file_name_from_path(pth):
return os.path.split(pth)[1];
def get_dir_from_path(pth):
return (os.path.split(pth)[0]+os.sep);
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/vbgui/BeatGUI.py
================================================
from visbeat3.AImports import *
VIEWER_INSTALLED = 1;
try:
import vbwidget as Viewer
except ImportError as e:
VIEWER_INSTALLED = 0;
AWARN("VBViewer not installed. Consider installing for full functionality.")
from ..TimeSignal import *
from ..EventList import *
#this is what media should call to get its gui object
def media_GUI_func(self):
if (self._gui is None):
self._gui = BeatGUI();
self._gui.media = self;
return self._gui;
class BeatGUI(AObject):
"""
"""
def AOBJECT_TYPE(self):
return 'BeatGUI';
def __init__(self, media=None, path=None, clear_temp=None):
"""If you provide a directory, it will look for a existing AFileManager.json in that directory, or create one if it does not already exist.
If you provide a json, it will use that json, unless the json doesn't exist, in which case it will complain...
"""
AObject.__init__(self, path=path);
if(media is not None):
self.media = media;
def initializeBlank(self):
AObject.initializeBlank(self);
self._widget = None;
self._media = None;
def getJSONName(self):
return self.AOBJECT_TYPE()+".json";
#########
#
@property
def media(self):
return self._getMedia();
def _getMedia(self):
return self._media;
@media.setter
def media(self, value):
self._setMedia(value);
def _setMedia(self, value):
self._media = value;
#
#
@property
def media_type(self):
return self._getMediaType();
def _getMediaType(self):
if(self.media is None):
return None;
else:
return self.media.AObjectType();
#
#
@property
def widget(self):
return self._getWidget();
def _getWidget(self):
if (self._widget is None):
self._widget = Viewer.VBVSignal();
return self._widget;
@widget.setter
def widget(self, value):
self._setWidget(value);
def _setWidget(self, value):
self._widget = value;
#
#
@property
def frame_rate(self):
return self._getFrameRate();
def _getFrameRate(self):
gfr = self.widget.frame_rate;
if (gfr is None):
media = self.media;
if (media is not None):
gfr = media.getFrameRate();
return gfr;
@frame_rate.setter
def frame_rate(self, value):
self._setFrameRate(value);
def _setFrameRate(self, value):
self.widget.frame_rate = float(value);
#
#
@property
def frame_offset(self):
return self._getFrameOffset();
def _getFrameOffset(self):
return self.widget.frame_offset;
@frame_offset.setter
def frame_offset(self, value):
self._setFrameOffset(value);
def _setFrameOffset(self, value):
self.widget.frame_offset = value;
#
def run(self, local_saliency=None, frame_rate = None, eventlist = 'default', frame_offset=None):
if(frame_rate is None):
# self.widget.frame_rate = float(self.getMedia().getFrameRate());
self.frame_rate = self.media._getFrameRate();
else:
# self.widget.frame_rate = float(frame_rate);
self.frame_rate = frame_rate;
if(local_saliency is None):
self.widget.signal = self.media.getLocalRhythmicSaliency().tolist();
# self.widget.signal = self.getBothWayVisualImpactEnvelope(highpass_window_seconds=None, force_recompute = True).tolist();
else:
self.widget.signal = local_saliency.tolist();
if(frame_offset is None):
self.frame_offset = 0;
elif(frame_offset is 'guess'):
self.frame_offset = self.guessFrameOffset();
else:
self.frame_offset = frame_offset;
if(eventlist is None):
self.widget.events = [];
elif(eventlist == 'default'):
self.widget.events = EventList._toGUIDicts(self.media.getEventList());
else:
self.widget.events = EventList._toGUIDicts(eventlist);
self.widget.data_string = self.media.getStringForHTMLStreamingBase64();
return self.widget;
def guessFrameOffset(self):
if(isinstance(self.media, Video)):
return self.media.reader.get_length() - self.media.n_frames();
else:
return 0;
def deactivateAllEvents(self):
newes = []
gevents = self.getEventDicts();
for e in gevents:
newe = e;
newe['is_active']=0;
newes.append(newe);
self.widget.events = [];
self.widget.events = newes;
def activateAllEvents(self):
newes = []
gevents = self.getEventDicts();
for e in gevents:
newe = e;
newe['is_active'] = 1;
newes.append(newe);
self.widget.events = [];
self.widget.events = newes;
def activatePattern(self, pattern=None, prefix=None, apply_to_active=None):
assert(pattern), "must provide pattern to activate"
newes = []
gevents = self.getGUIEventDicts();
counter = 0;
prefix_length = 0;
if(prefix_length is not None):
prefix_length = len(prefix);
for i, e in enumerate(gevents):
if (apply_to_active):
if (e.get('is_active')):
if (counter < prefix_length):
e['is_active']=prefix[counter];
else:
e['is_active'] = pattern[(counter - prefix_length) % len(pattern)];
counter = counter + 1;
else:
print(("Skipping beat {}, inactive".format(i)));
else:
if (i < prefix_length):
e['is_active'] = prefix[i];
else:
e['is_active'] = pattern[(i - prefix_length) % len(pattern)];
newes.append(e);
self.widget.events = [];
self.widget.events = newes;
def shiftEventsByNFrames(self, n_frames=None):
assert(n_frames), "must provide number of frames to shift by"
newes = []
gevents = self.getEventDicts();
sample_step = np.true_divide(1.0,self.getFrameRate());
for e in gevents:
newe = e;
newe['start'] = newe['start']+n_frames*sample_step;
newes.append(newe);
self.widget.events = [];
self.widget.events = newes;
def getActiveEventTimes(self):
gevents = self.getEventDicts(active_only=True);
revents = []
for e in gevents:
revents.append(e.get('time'));
return np.asarray(revents);
def getEventTimes(self):
gevents = self.getEventDicts();
revents = []
for e in gevents:
revents.append(e.t);
return np.asarray(revents);
def getEvents(self, active_only=None):
return Event._FromGUIDicts(self.getEventDicts(active_only = active_only));
def getEventList(self, active_only=None):
elist = EventList._FromGUIDicts(self.getEventDicts(active_only=active_only));
elist.setInfo(label='html_frame_offset', value=self.getFrameOffset());
return elist;
def getActiveEvents(self):
return self.getEvents(active_only=True);
def getEventDicts(self, active_only = None):
gevents = self.widget.events[:];
if(not active_only):
return gevents;
else:
nevents = []
for e in gevents:
if(e.get('is_active')):
nevents.append(e);
return nevents;
def saveEvents(self, save_path = None):
elist = self.getEventList(active_only=False);
if(save_path is not None):
elist.writeToJSON(json_path=save_path);
self.widget.last_save_path = save_path;
else:
save_path = self.widget.last_save_path;
if(save_path is None):
save_path = uiGetSaveFilePath(file_extension='.json');
if(save_path is not None):
elist.writeToJSON(json_path=save_path);
self.widget.last_save_path = save_path;
def saveEventsAs(self, save_path = None):
elist = self.getEventList(active_only=False);
if (save_path is not None):
elist.writeToJSON(json_path=save_path);
self.widget.last_save_path = save_path;
print(('savepath not none {}'.format(save_path)))
else:
save_path = uiGetSaveFilePath(file_extension='.json');
print(('savepath from ui {}'.format(save_path)))
if (save_path is not None):
print(('save path from ui {}'.format(save_path)));
elist.writeToJSON(json_path=save_path);
self.widget.last_save_path = save_path;
print(save_path)
def setEvents(self, events):
self.widget.events = Event._ToGUIDicts(events);
def setEventList(self, event_list):
if(event_list.getInfo('html_frame_offset') is not None):
self.widget.frame_offset = event_list.getInfo('html_frame_offset');
self.widget.events = event_list._toGUIDicts();
def loadEvents(self, load_path = None):
if(load_path is None):
load_path = uiGetFilePath();
elist = EventList();
elist.loadFromJSON(json_path=load_path);
self.setEventList(event_list = elist);
def getEventListWithSelectedSegments(self):
eventlist = self.getEventList();
events = eventlist.events;
segments = [];
for i, e in enumerate(events):
if(e.direction>-1): # meaning not a back beat
newseg = [];
for si in range(i, len(events)):
newseg.append(si);
if(events[si].direction<0): # meaning a back beat
break;
segments.append(newseg);
eventlist.setInfo(label='selected_segments', value=segments);
return eventlist;
================================================
FILE: src/video2npz/visbeat3/build/lib/visbeat3/vbgui/__init__.py
================================================
================================================
FILE: src/video2npz/visbeat3/build/scripts-3.7/dancefer
================================================
#!/opt/anaconda3/envs/py37/bin/python
import sys
import matplotlib
matplotlib.use('PS')
import visbeat3
source_url = 'https://www.youtube.com/watch?v={}'.format(sys.argv[0]);
target_url = 'https://www.youtube.com/watch?v={}'.format(sys.argv[1]);
output_path = sys.argv[2];
result = visbeat3.AutoDancefer(source=source_url, target = target_url,
output_path = output_path,
synch_video_beat = 0,
synch_audio_beat = 0,
beat_offset = 64,
nbeats = 128);
result.play();
================================================
FILE: src/video2npz/visbeat3/setup.cfg
================================================
[metadata]
# This includes the license file(s) in the wheel.
# https://wheel.readthedocs.io/en/stable/user_guide.html#including-license-files-in-the-generated-wheel-file
license_files = LICENSE
[bdist_wheel]
# This flag says to generate wheels that support both Python 2 and Python
# 3. If your code will not run unchanged on both Python 2 and 3, you will
# need to generate separate wheels for each Python version that you
# support. Removing this line (or setting universal to 0) will prevent
# bdist_wheel from trying to make a universal wheel. For more see:
# https://packaging.python.org/guides/distributing-packages-using-setuptools/#wheels
universal=0
================================================
FILE: src/video2npz/visbeat3/setup.py
================================================
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name="visbeat3",
version="0.0.8",
author="Haofan Wang",
author_email="haofanwang.ai@gmail.com",
description="Python3 Implementation for 'Visual Rhythm and Beat' SIGGRAPH 2018",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/haofanwang/visbeat3",
packages=setuptools.find_packages(),
# install_requires=[
# 'numpy',
# 'scipy',
# 'bs4',
# 'librosa==0.6.0',
# 'imageio==2.9.0',
# 'requests',
# 'moviepy==1.0.3',
# 'termcolor',
# 'youtube-dl',
# 'matplotlib',
# 'numba==0.48.0'
# ],
scripts=['bin/dancefer'],
include_package_data=True,
package_data={'data': ['visbeat3/assets/*']},
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
],
)
================================================
FILE: src/video2npz/visbeat3/test.py
================================================
import visbeat3 as vb
import os
video_dir = '../videos/'
tempos = {}
# try:
# for file in os.listdir(video_dir):
# if file == '.DS_Store':
# continue
# vlog = vb.PullVideo(name=file, source_location=video_dir+file, max_height=360)
# # vbeats = vlog.getVisualBeatSequences(search_window=None)[0]
# # print("vbeats are", vbeats)
# vb.Video.getVisualTempo = vb.Video_CV.getVisualTempo
# tempo = vlog.getVisualTempo()
# print(file, "tempo", tempo)
# tempos[file] = tempo
# finally:
# print(tempos)
vlog = vb.PullVideo(source_location="../videos/wzk_vlog_beat_enhance1_track1238.mp4", max_height=360)
vb.Video.getVisualTempo = vb.Video_CV.getVisualTempo
tempo = vlog.getVisualTempo()
print(tempo)
# vbeats = vlog.getVisualBeatSequences(search_window=None)[0]
# for vbeat in vbeats:
# print(vbeat.start, vbeat.type, vbeat.weight, vbeat.index, vbeat.unrolled_start, vbeat.direction)
================================================
FILE: src/video2npz/visbeat3/visbeat3/ADefines.py
================================================
# AD_DEBUG = 1;
AD_DEBUG = 0;
================================================
FILE: src/video2npz/visbeat3/visbeat3/AFileManager.py
================================================
from .AObject import *
#import shutil
from distutils.dir_util import copy_tree
class AFileManager(AObject):
"""AFileManager (class): Manages assets. This should really be replaced with a database of some sort...
Attributes:
todo
"""
@staticmethod
def AOBJECT_TYPE():
return 'AFileManager';
def getJSONPath(self):
return self.getPath();
def __init__(self, path=None, clear_temp=None):
"""If you provide a directory, it will look for a existing AFileManager.json in that directory, or create one if it does not already exist.
If you provide a json, it will use that json, unless the json doesn't exist, in which case it will complain...
"""
AObject.__init__(self, path=path);
# self.initializeBlank();
self.initWithPath(path=path, clear_temp=clear_temp);
def initializeBlank(self):
AObject.initializeBlank(self);
self.directories = {};
def getJSONName(self):
return self.AOBJECT_TYPE()+".json";
def initWithPath(self, path=None, clear_temp=None):
oldpath = None
newpath = path;
if(path):
if(os.path.isfile(path)):
self.loadFromJSON(self.getJSONPath()); #assume path property is already set to 'path'
oldpath = self.getPath(); #whatever was in the json, having overwritten path property
elif(os.path.isdir(path)):
json_file_path = path+os.sep+self.getJSONName();
self.setPath(json_file_path);
if(os.path.isfile(self.getJSONPath())):
self.loadFromJSON(json_file_path);
oldpath = self.getPath();
newpath = json_file_path;
# self.setPath(file_path=json_file_path);
else:
newpath=self.getJSONPath()
self.writeToJSON(json_path=newpath);#no json file found, so we create one
else:
assert False, "Given AFileManager path is neither an existing directory or file! path: {} (AFileManager.py)".format(path)
self.setPath(file_path=newpath);
if(oldpath):
oldir = get_dir_from_path(pathstring(oldpath));
newdir = get_dir_from_path(pathstring(newpath));
if(oldir != newdir):
AWARN("FILEMANAGER FOUND FILE MOVED FROM:\n{}\nTO:\n{}\nUPDATING DIRECTORIES...".format(oldir,
newdir));
for d in self.directories:
dpth = self.directories[d];
if(dpth.startswith(oldir)):
dpthst = dpth.lstrip(oldir);
self.directories[d]=os.path.join(newdir,dpthst);
AWARN("{} updated to {}".format(dpth, self.directories[d]));
self.setDir('data', pathstring(self.getDirectoryPath()+os.sep+"Data"+os.sep));
self.setDir('backup', pathstring(self.getDir('data')+"Backups"+os.sep));
self.setDir('temp', pathstring(self.getDir('data')+"TEMP"+os.sep));
temp_dir = self.getDir('temp');
if(os.path.isdir(temp_dir) and (clear_temp)):
for the_file in os.listdir(temp_dir):
file_path = os.path.join(temp_dir, the_file);
try:
if os.path.isfile(file_path):
os.remove(file_path);
#os.unlink(file_path);
#elif os.path.isdir(file_path): shutil.rmtree(file_path)
except Exception as e:
print(e)
make_sure_path_exists(temp_dir);
#Video.VIDEO_TEMP_DIR = temp_dir;
def setDir(self, name, path):
# AWARN("setting {} to {}".format(name, path))
# assert(name is not 'log')
self.directories[name]=path;
make_sure_path_exists(path);
return path;
def addDir(self, name):
assert(name not in self.directories), "tried to add {} dir to AFileManager, but this dir is already set"
return self.setDir(name, pathstring(self.getDirectoryPath()+os.sep+name+os.sep));
def getDir(self, name):
# printDictionary(self.directories)
return self.directories.get(name);
def emptyDir(self, name):
dpth = self.getDir(name);
if(dpth is not None and os.path.isdir(dpth)):
shutil.rmtree(dpth);
make_sure_path_exists(dpth);
def deleteDir(self, name):
dpth = self.getDir(name);
if (dpth is not None and os.path.isdir(dpth)):
shutil.rmtree(dpth);
d = dict(self.directories);
del d[name];
self.directories=d;
def toDictionary(self):
d = AObject.toDictionary(self);
d['directories']=self.directories;
#serialize class specific members
return d;
def copyPathToDir(self, path_to_copy, dest_dir):
dest_path = self.getDir(dest_dir);
if(dest_path):
if(os.path.isdir(path_to_copy)):
copy_tree(src=path_to_copy, dst=dest_path);
elif(os.path.isfile(path_to_copy)):
shutil.copy2(path_to_copy, dest_path)
return;
def copyDirToPath(self, dir_to_copy, dest_path):
src_path = self.getDir(dir_to_copy);
if(src_path):
if(os.path.isdir(dest_path)):
copy_tree(src=src_path, dst=dest_path);
return;
@staticmethod
def copyRandomFractionOfFilesInSourceDir(source_dir, dest_dir, fraction=1.0, ext=None):
"""
Copies a random fraction of files in source directory... Wrote this for splitting training/test data in ML applications.
:param source_dir:
:param dest_dir:
:param fraction:
:param ext:
:return:
"""
directories = []
subdirnames = []
filepaths = [];
for filename in os.listdir(source_dir):
path = os.path.join(source_dir, filename)
if os.path.isdir(path):
directories.append(path)
subdirnames.append(filename)
else:
# namepart, extpart = os.path.splitext(filename);
if((ext is None) or filename.lower().endswith(ext)):
filepaths.append(path);
n_to_copy = int(len(filepaths)*fraction);
random_seed = 0;
random.seed(random_seed);
random.shuffle(filepaths);
copy_sources = filepaths[:n_to_copy];
for src, dst in zip(copy_sources, [dest_dir]*len(copy_sources)):
#print("src: {}\ndst: {}".format(src, dst));
shutil.copy2(src, dst);
for d in range(len(directories)):
subdest = pathstring(os.path.join(dest_dir,subdirnames[d])+os.sep);
make_sure_dir_exists(subdest);
AFileManager.copyRandomFractionOfFilesInSourceDir(source_dir=directories[d], dest_dir=subdest, fraction=fraction, ext=ext);
def initFromDictionary(self, d):
AObject.initFromDictionary(self, d);
self.directories = d['directories'];
def save(self):
if(os.path.isfile(self.getJSONPath())):
os.rename(self.getJSONPath(), self.getDir('backup')+os.sep+self.AOBJECT_TYPE()+".json");
self.writeToJSON(self.getJSONPath());
================================================
FILE: src/video2npz/visbeat3/visbeat3/AFuncDict.py
================================================
from .AParamDict import *
import pickle as pickle
import os
class AFuncDict(AParamDict):
"""AFuncDict (class): Extends AParamDict so that functions can be assigned to features and called whenever
computing those features is necessary.
Attributes:
data: name -> value, params
feature funcs: name -> function for evaluating
"""
def __init__(self, owner=None, name=None, path=None):
AParamDict.__init__(self, owner=owner, name=name, path=path);
self.functions = {};
def getEntry(self, name=None, params=None, force_recompute=False):
d = self.data.get(name);
if((d is not None) and (not force_recompute)):
return d;
else:
f = self.getFunction(name=name);
if(f is not None):
if(params is not None):
if(not params.get('force_recompute')):
params.update(dict(force_recompute=force_recompute));
self.setValue(name=name, value=f(self=self.owner, **params), params=params, modified=True);
else:
self.setValue(name=name, value=f(self=self.owner, force_recompute=force_recompute), params=params, modified=True);
return self.data.get(name);
return None;
def getValue(self, name=None, params=None, force_recompute=False):
d = self.getEntry(name=name, params=params, force_recompute=force_recompute);
if(d is not None):
return d.get('value');
else:
return None;
def getParams(self, name=None):
d = self.data.get(name);
if(d is not None):
return d.get('params');
else:
return None;
def getFunction(self, name=None):
return self.functions.get(name);
def setValue(self, name, value=None, params=None, modified=True):
self.data[name]['value']=value;
self.data[name]['params']=params;
self.setEntryModified(name=name, is_modified=modified)
#self.data[name]['modified']=modified;
def setFunction(self, name, function=None):
self.functions[name]=function;
def saveEntry(self, name, path, force=False):
"""Save one entry to one file."""
if(self.data.get(name) is None):
return None;
if(self.isEntryModified(name=name) or force or (not os.path.isfile(path))):
#pickleToPath
f = open(path, 'wb');
pickle.dump(self.getEntry(name=name), f, protocol=2);
f.close();
self.setEntryModified(name=name, is_modified=False);
#assert(False), "should not be saving in this test";
return True;
def setEntryModified(self, name, is_modified=True):
self.data[name]['modified']=is_modified;
if(is_modified):
self.setModified(is_modified=True);
def isEntryModified(self, name):
entry = self.data.get(name);
if(entry is not None):
m=entry.get('modified');
if(m is not None):
return m;
else:
return True;
else:
assert(False), "checking mod bit on entry that does not exist"
def isModified(self):
return self.modified;
def setModified(self, is_modified):
self.modified=is_modified;
def save(self, path, force=False):
"""save all entries to one file."""
if(force or self.isModified()):
f = open(path, 'wb');
pickle.dump(self.data, f, protocol=2);
f.close();
self.setModified(is_modified=False);
#assert(False), "should not be saving in this test";
return True;
def loadEntry(self, name, path):
"""load one entry from one file."""
f=open(path, 'rb');
self.setEntry(name=name, d=pickle.load(f));
f.close();
self.setEntryModified(name=name, is_modified=False);
return True;
def load(self, path):
"""Load a set of entries all from one file."""
f=open(path, 'rb');
newd = pickle.load(f);
self.data.update(newd);
f.close();
return True;
def getKeyList(self):
return list(self.data.keys());
def getFunctionList(self):
return list(self.functions.keys());
================================================
FILE: src/video2npz/visbeat3/visbeat3/AImports.py
================================================
#AImports
from . import ADefines as defines
import os
import os.path
import errno
import json
import pickle as pickle
import glob
import subprocess
from operator import truediv
import shutil
import time
from time import gmtime, strftime, localtime
import random
from . import fileui
try:
from termcolor import colored
def AWARN(message):
if (defines.AD_DEBUG):
print((colored(message, 'red')))
def AINFORM(message):
if(defines.AD_DEBUG):
print((colored(message, 'blue')))
except ImportError:
if (defines.AD_DEBUG):
print("You do not have termcolor installed (pip install termcolor). AWARN will just show as plain print statements when defines.AD_DEBUG==True...")
def AWARN(message):
if (defines.AD_DEBUG):
print(message);
def AINFORM(message):
if (defines.AD_DEBUG):
print(message);
def local_time_string():
return strftime("%Y-%m-%d_%H:%M:%S", localtime());
def get_temp_file_path(final_file_path="TEMP", temp_dir_path = None):
pparts = os.path.split(final_file_path);
destfolder = pparts[0]+os.sep;
tempdir = temp_dir_path;
if(tempdir is None):
tempdir='.';
destfolder=pathstring(tempdir+os.sep);
tempname = 'TEMP_'+pparts[1];
temptry = 0;
while(os.path.isfile(destfolder+tempname)):
temptry=temptry+1;
tempname = 'TEMP{}_'.format(temptry)+pparts[1];
return pathstring(destfolder+tempname);
def runningInNotebook():
try:
shell = get_ipython().__class__.__name__
if shell == 'ZMQInteractiveShell':
return True # Jupyter notebook or qtconsole
elif shell == 'TerminalInteractiveShell':
return False # Terminal running IPython
else:
return False # Other type (?)
except NameError:
return False # Probably standard Python interpreter
def getshellname():
try:
shell = get_ipython().__class__.__name__
return shell;
except NameError:
return False # Probably standard Python interpreter
def runningInSpyder():
return 'SpyderKernel' in str(get_ipython().kernel.__class__);
def pickleToPath(d, path):
# assert(False)
print("pickling")
f = open(path, 'wb');
pickle.dump(d, f, protocol=2);
f.close();
return True;
def unpickleFromPath(path):
f=open(path, 'rb');
d=pickle.load(f);
f.close();
return d;
def make_sure_path_exists(path):
try:
os.makedirs(path)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
def make_sure_dir_exists(path):
pparts = os.path.split(path);
destfolder = pparts[0]+os.sep;
try:
os.makedirs(destfolder)
except OSError as exception:
if exception.errno != errno.EEXIST:
raise
def safe_file_name(input_string):
return ''.join([i if ord(i) < 128 else '_' for i in input_string]);
def pathstring(path):
return path.replace(os.sep+os.sep, os.sep);
def is_interactive():
import __main__ as main
return not hasattr(main, '__file__')
def printOb(obj):
for attr in dir(obj):
print("#### Obj.%s = %s\n" % (attr, getattr(obj, attr)))
def pathstring(path):
return path.replace(os.sep+os.sep, os.sep);
def get_prepended_name_file_path(original_file_path, string_to_prepend):
pparts = os.path.split(original_file_path);
destfolder = pparts[0]+os.sep;
pname = string_to_prepend+pparts[1];
return pathstring(destfolder+pname);
def safe_file_name(input_string):
return ''.join([i if ord(i) < 128 else '_' for i in input_string]);
def change_extension(input_path, new_ext):
nameparts = os.path.splitext(input_path);
return nameparts[0]+new_ext;
def printDictionary(obj):
if type(obj) == dict:
for k, v in list(obj.items()):
if hasattr(v, '__iter__'):
print(k)
printDictionary(v)
else:
print('%s : %s' % (k, v))
elif type(obj) == list:
for v in obj:
if hasattr(v, '__iter__'):
printDictionary(v)
else:
print(v)
else:
print(obj)
def spotgt_shift_bit_length(x):
#smallest power of two greater than
return 1<<(x-1).bit_length()
def get_file_name_from_path(pth):
return os.path.split(pth)[1];
def get_dir_from_path(pth):
return (os.path.split(pth)[0]+os.sep);
def get_file_names_from_paths(pths):
r = [];
for p in pths:
r.append(get_file_name_from_path(p));
return r;
def writeDictionaryToJSON(d, json_path=None):
if(json_path):
with open(json_path, 'w') as outfile:
json.dump(d, outfile, sort_keys = True, indent = 4, ensure_ascii=False);
def vtt_to_srt(fileContents):
replacement = re.sub(r'([\d]+)\.([\d]+)', r'\1,\2', fileContents)
replacement = re.sub(r'WEBVTT\n\n', '', replacement)
replacement = re.sub(r'^\d+\n', '', replacement)
replacement = re.sub(r'\n\d+\n', '\n', replacement)
return replacement
================================================
FILE: src/video2npz/visbeat3/visbeat3/AObject.py
================================================
#AO#labels#AObject
import os
import json
from .AParamDict import *
from . import fileui
class AObject(object):
"""AObject (class): This is a paarent class used to implement any comon serialization or typing we might want to do later
Attributes:
labels: dictionary of meta_data
save, load, and clear funcs: these are hooks for functions that manage the object's data on disk.
"""
AOBJECT_BASE_PATH=None;
def __init__(self, path=None, **kwargs):
self.initializeBlank();
if(path):
self.setPath(file_path=path, **kwargs);
def initializeBlank(self):
self.a_info = {'AObjectType': self.AOBJECT_TYPE()};
# self.a_data = AParamDict(owner=self, name='a_data');
self.save_func = None;
self.load_func = None;
self.clear_func = None;
def setPath(self, file_path=None, **kwargs):
if(file_path):
self.a_info['file_path'] = pathstring(file_path);
pparts = os.path.split(self.a_info['file_path']);
self.a_info['file_name'] = pparts[1];
self.a_info['directory_path']=pparts[0];
filename = self.a_info.get('file_name');
if(filename):
nameparts = os.path.splitext(filename);
self.a_info['file_base_name'] = nameparts[0];
self.a_info['file_ext'] = nameparts[1];
self.a_info['base_path'] = kwargs.get('base_path');
if(self.a_info['base_path'] is None):
self.a_info['base_path'] = AObject.AOBJECT_BASE_PATH;
def getPath(self):
if('file_path' in self.a_info):
return self.a_info['file_path'];
else:
return None;
def _showFile(self):
if(fileui.Show is not None):
fileui.Show(self.getPath());
def _open(self):
if(fileui.Open is not None):
fileui.Open(self.getPath());
def getRelativePath(self, base_path=None):
base = base_path;
if(base is None):
base = self.a_info.get('base_path');
if(base is None):
AWARN("Base path not set!");
return str(self.getPath());
def getFileName(self):
if('file_name' in self.a_info):
return self.a_info['file_name'];
else:
return None;
def getFileExtension(self):
if('file_ext' in self.a_info):
return self.a_info['file_ext'];
else:
return None;
def getDirectoryPath(self):
return self.a_info.get('directory_path')
def setInfo(self, label, value):
self.a_info[label]=value;
def getInfo(self, label):
return self.a_info.get(label);
def loadFromJSON(self, json_path=None):
if(json_path):
self.setPath(file_path=json_path);
if('file_path' in self.a_info):
json_text=open(self.a_info['file_path']).read();
d = json.loads(json_text);
self.initFromDictionary(d);
def writeToJSON(self, json_path=None):
#with open(jsonpath+self.name+'.json', 'w') as outfile:
if(not json_path):
json_path = self.a_info.get('file_path');
if(json_path):
with open(json_path, 'w') as outfile:
json.dump(self.toDictionary(), outfile, sort_keys = True, indent = 4, ensure_ascii=False);
def serializeInfo(self):
return self.a_info;
def save(self, features_to_save='all', overwrite=True, **kwargs):
if(self.save_func):
self.save_func(self, features_to_save=features_to_save, overwrite=overwrite, **kwargs);
else:
AWARN("SAVE FUNCTION HAS NOT BEEN PROVIDED FOR {} INSTANCE".format(self.AOBJECT_TYPE()));
def load(self, features_to_load=None, **kwargs):
if(self.load_func):
self.load_func(self, features_to_load=features_to_load, **kwargs);
else:
AWARN("LOAD FUNCTION HAS NOT BEEN PROVIDED FOR {} INSTANCE".format(self.AOBJECT_TYPE()));
########### "VIRTUAL" FUNCTIONS #############
@staticmethod
def AOBJECT_TYPE():
return 'AObject';
def toDictionary(self):
d = {'a_info': self.serializeInfo()};
return d;
def initFromDictionary(self, d):
self.a_info = d.get('a_info');
# ##Example of how these functions should be written in a subclass, here we call the subclass 'AssetManager'
# def AOBJECT_TYPE(self):
# return 'AssetManager';
#
# def toDictionary(self):
# d = AObject.toDictionary(self);
# #serialize class specific members
# return d;
#
# def initFromDictionary(self, d):
# AObject.initFromDictionary(self, d);
# #do class specific inits with d;
================================================
FILE: src/video2npz/visbeat3/visbeat3/AParamDict.py
================================================
from .AImports import *
class AParamDict(object):
"""AParamDict (class): Dictionary that stores values and the parameters used to compute those values. I use this
class for two things. The first is to store parameters for reproducability. The second is to only recompute
values when functions are called with different parameters (some of this latter functionality is tied up in
code that isn't part of the Lite release).
Attributes:
data: name -> value, params
"""
def __init__(self, owner=None, name=None, path=None):
self.name=name;
self.data = {};
self.owner=owner;
self.modified=False;
def getEntry(self, name=None, params=None, force_recompute=False):
d = self.data.get(name);
if((d is not None) and (not force_recompute)):
return d;
return None;
def setEntry(self, name, d):
assert(name!='all' and name!='each'),"Entry named '{}' is reserved in AParamDict".format(name);
self.data[name]=d;
def removeEntry(self, name, assert_if_absent=True, set_modified = True):
if(assert_if_absent):
assert(name in self.data),"Tried to remove entry {} that was not already in {}".format(name, self.__class__);
popentry = self.data.pop(name, None);
if(set_modified):
self.setModified(set_modified);
return popentry;
def hasEntry(self, name=None):
return (self.data.get(name) is not None);
def getValue(self, name=None, params=None, force_recompute=False):
d = self.getEntry(name=name, params=params, force_recompute=force_recompute);
if(d is not None):
return d.get('value');
else:
return None;
def getParams(self, name=None):
d = self.data.get(name);
if(d is not None):
return d.get('params');
else:
return None;
def setValue(self, name, value=None, params=None, modified=True):
self.data[name]['value']=value;
self.data[name]['params']=params;
self.setEntryModified(name=name, is_modified=modified)
def saveEntry(self, name, path, force=False):
"""Save one entry to one file."""
if(self.hasEntry(name=name) is None):
return None;
if(self.isEntryModified(name=name) or force or (not os.path.isfile(path))):
f = open(path, 'wb');
pickle.dump(self.getEntry(name=name), f, protocol=2);
f.close();
self.setEntryModified(name=name, is_modified=False);
return True;
def setEntryModified(self, name, is_modified=True):
self.data[name]['modified']=is_modified;
if(is_modified):
self.setModified(is_modified=True);
def isEntryModified(self, name):
m=self.data[name].get('modified');
if(m is not None):
return m;
else:
return True;
def isModified(self):
return self.modified;
def setModified(self, is_modified):
self.modified=is_modified;
def save(self, path, force=False):
"""save all entries to one file."""
if(force or self.isModified()):
f = open(path, 'wb');
pickle.dump(self.data, f, protocol=2);
f.close();
self.setModified(is_modified=False);
return True;
def loadEntry(self, name, path):
"""load one entry from one file."""
f=open(path, 'rb');
self.setEntry(name=name, d=pickle.load(f));
f.close();
self.setEntryModified(name=name, is_modified=False);
return True;
def load(self, path):
"""Load a set of entries all from one file."""
f=open(path, 'rb');
newd = pickle.load(f);
self.data.update(newd);
f.close();
return True;
def getKeyList(self):
return list(self.data.keys());
================================================
FILE: src/video2npz/visbeat3/visbeat3/Audio.py
================================================
from .EventList import *
from .TimeSignal1D import *
from scipy.io.wavfile import write
import librosa
import librosa.display
from scipy import signal, fftpack
class Audio(TimeSignal1D):
"""Audio (class): A sound, and a bunch of convenience functions to go with it.
Attributes:
x: the sound signal
sampling_rate: the sampling rate
"""
FEATURE_FUNCS = TimeSignal1D.FEATURE_FUNCS.copy();
def __init__(self, path=None, sampling_rate=None, x=None, name=None):
#VBObject.__init__(self, path=path);
TimeSignal1D.__init__(self, path=path, sampling_rate=sampling_rate, x=x);
#self.initializeBlank();
if(name is not None):
self.name = name;
if(path):
self.loadFile();
if(self.name is None):
self.name = self.getInfo('file_name')
#
@property
def name(self):
return self.getName();
def getName(self):
return self._name;
@name.setter
def name(self, value):
self._setName(value);
def _setName(self, value):
self._name = value;
#
def initializeBlank(self):
self.name = None;
TimeSignal1D.initializeBlank(self);
self.n_channels = 1;
def _getFrameRate(self):
return self.getOnsetSamplingRate();
def clone(self):
clone = Audio();
clone.setPath(self.getPath());
clone.x = self.x.copy();
clone.sampling_rate = self.sampling_rate;
clone.n_channels = self.n_channels;
stereo = self.getStereo();
if (stereo is not None):
clone.setInfo('stereo_signal', stereo);
clone.setInfo('stereo_sampling_rate', self.getInfo('stereo_sampling_rate'));
return clone;
def loadFile(self, file_path=None, sampling_rate=None, convert_to_mono=True):
if(file_path):
self.setPath(file_path=file_path);
if('file_path' in self.a_info):
self.x, self.sampling_rate = librosa.load(self.a_info['file_path'],sr=sampling_rate, mono=convert_to_mono);
if(len(self.x.shape)>1):
self.a_info['stereo_signal']=self.x;
self.setInfo('stereo_sampling_rate', self.sampling_rate);
self.x = np.mean(self.x, axis = 0)
print("averaged stereo channels");
def getStereo(self):
return self.a_info.get('stereo_signal');
def getStereoSamplingRate(self):
return self.getInfo('stereo_sampling_rate');
def getStringForHTMLStreamingBase64(self):
encoded = self.getStereoEncodedBase64WAV();
return "data:audio/wav;base64,{0}".format(encoded.decode('ascii'));
def getStereoEncodedBase64WAV(self):
sig = self.getStereo();
sr = self.getStereoSamplingRate();
if (sig is None):
sig = self.getSignal();
sr = self.sampling_rate;
saudio = _make_wav(sig, sr);
encoded = base64.b64encode(saudio);
return encoded;
def getMonoEncodedBase64WAV(self):
sig = self.getSignal();
sr = self.sampling_rate;
saudio = _make_wav(sig, sr);
encoded = base64.b64encode(saudio);
return encoded;
def getLocalRhythmicSaliency(self, **kwargs):
return self.getOnsetEnvelope(**kwargs);
def play(self, autoplay = None):
"""
Play audio. Works in Jupyter. if notebook, audio will play normalized -- this is something html5 audio seems to do by default.
:param autoplay:
:return:
"""
if(ISNOTEBOOK):
# if(normalize):
audiodisp = vb_get_ipython().display.Audio(data=self.getSignal(), rate=self.sampling_rate, autoplay=autoplay);
vb_get_ipython().display.display(audiodisp);
# vb_get_ipython().display.display(vb_get_ipython().display.Audio(data=self.getSignal(), rate=self.sampling_rate, autoplay=False))
# else:
# audiodisp = vb_get_ipython().display.Audio(data=self.getMonoEncodedBase64WAV(), rate=self.sampling_rate,
# autoplay=autoplay);
# vb_get_ipython().display.display(audiodisp);
# print("html render")
# htmlstr = self.getStringForHTMLStreamingBase64()
# ahtml = HTML(data=''''''.format(self.name, htmlstr));
# IPython.display.display(ahtml);
else:
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paFloat32,
channels=self.n_channels,
rate=self.sampling_rate,
output=True,
output_device_index=1
)
stream.write(self.getSignal())
stream.stop_stream();
stream.close()
p.terminate()
def playBeats(self, indices=None, beats=None):
beat_inds = indices;
if(beats is None):
beats = self.getBeatEvents();
if(beat_inds is None):
beat_inds = [0, len(beats)-1];
if(not isinstance(beat_inds, list)):
beat_inds=[beat_inds-1, beat_inds, beat_inds+1];
if(beat_inds[0]<0):
start_time = 0;
else:
start_time = beats[beat_inds[0]].start;
if(beat_inds[-1]>len(beats)):
end_time = self.getDuration();
else:
end_time = beats[beat_inds[-1]].start;
self.playSegment(time_range = [start_time, end_time]);
def AudioClipFromBeatRange(self, beat_range, beats=None):
if(beats is None):
beats = self.getBeatEvents();
if(beat_range is None):
beat_range = [0, len(beats)-1];
if(beat_range[1] is None):
beat_range[1]=len(beats)-1;
return self.AudioClip(start=beats[beat_range[0]].start, end=beats[beat_range[1]].start);
def playSegment(self, time_range, autoplay=None):
start_time = time_range[0];
end_time = time_range[1];
if(isinstance(start_time, Event)):
start_time = start_time.start;
if(isinstance(end_time, Event)):
end_time = end_time.start;
if(ISNOTEBOOK):
audiodisp = vb_get_ipython().display.Audio(data=self.getSignalSegment(time_range=[start_time, end_time]), rate=self.sampling_rate, autoplay=autoplay);
vb_get_ipython().display.display(audiodisp);
# vb_get_ipython().display.display(vb_get_ipython().display.Audio(data=self.getSignal(), rate=self.sampling_rate, autoplay=False))
else:
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paFloat32,
channels=self.n_channels,
rate=self.sampling_rate,
output=True,
output_device_index=1
)
stream.write(self.getSignalSegment(time_range=[start_time, end_time]))
stream.stop_stream();
stream.close()
p.terminate()
def writeToFile(self, output_path=None, output_sampling_rate=None):
assert(output_path), "must provide path to save audio."
data = self.getSignal();
scaled = np.int16(data/np.max(np.abs(data)) * 32767)
if(output_sampling_rate is None):
output_sampling_rate=44100
write(output_path, output_sampling_rate, scaled)
def setValueRange(self, value_range=None):
if(value_range is None):
value_range = [-1,1];
TimeSignal1D.setValueRange(self, value_range=value_range);
def resample(self, sampling_rate):
new_n_samples = sampling_rate*self.getDuration();
self.x = sp.signal.resample(self.x, int(new_n_samples));
self.sampling_rate = sampling_rate;
def GetResampled(self, sampling_rate):
new_a = self.clone();
new_a.resample(sampling_rate=sampling_rate);
return new_a;
def AlignedTo(self, B):
assert(False),'Abe needs to fix -- broke when messing with alignment code for video';
A = self.clone();
if(A.sampling_rate !=B.sampling_rate):
A.resample(B.sampling_rate);
a_signal = A.getSignal();
b_signal = B.getSignal();
a_duration = self.getDuration();
if(len(a_signal) < len(b_signal)):
siglen = spotgt_shift_bit_length(len(b_signal));
else:
siglen = spotgt_shift_bit_length(len(a_signal));
npada = siglen-len(a_signal);
if(npada>0):
a_signal = np.pad(a_signal, (0,npada), 'constant', constant_values=(0, 0));
npadb = siglen-len(b_signal);
if(npadb>0):
b_signal = np.pad(b_signal, (0,npadb), 'constant', constant_values=(0, 0));
Af = fftpack.fft(a_signal);
Bf = fftpack.fft(b_signal);
Ar = Af.conjugate();
Br = Bf.conjugate();
# Ar = -Af.conjugate();
# Br = -Bf.conjugate();
ashift = np.argmax(np.abs(fftpack.ifft(Ar * Bf)));
print(ashift);
print((np.argmax(np.abs(fftpack.ifft(Af * Br)))));
a_return = Audio();
a_return.n_channels = 1;
a_return.sampling_rate = B.sampling_rate;
a_return.x = np.roll(a_signal, ashift);
return a_return;
def getOffsetFrom(self, B):
return -self.getShiftAmountTo(B);
def getShiftAmountTo(self, B):
"""
Get amount to shift by in seconds (to shift this to alignment with B)
"""
a_signal = self.getSignal();
b_signal = B.getSignal();
a_duration = self.getDuration();
if(self.sampling_rate !=B.sampling_rate):
ansamps = a_duration*B.sampling_rate;
a_signal = sp.signal.resample(a_signal, int(ansamps));
# a_signal = librosa.resample(a_signal, self.sampling_rate, B.sampling_rate, res_type='kaiser_fast');
if(len(a_signal) < len(b_signal)):
siglen = spotgt_shift_bit_length(len(b_signal));
else:
siglen = spotgt_shift_bit_length(len(a_signal));
npada = siglen-len(a_signal);
if(npada>0):
a_signal = np.pad(a_signal, (0,npada), 'constant', constant_values=(0, 0));
npadb = siglen-len(b_signal);
if(npadb>0):
b_signal = np.pad(b_signal, (0,npadb), 'constant', constant_values=(0, 0));
# if(len(a_signal) < len(b_signal)):
# npad = len(b_signal)-len(a_signal);
# a_signal = np.pad(a_signal, (0,npad), 'constant', constant_values=(0, 0));
# print('pad1');
#
# if (len(b_signal) < len(a_signal)):
# npad = len(a_signal) - len(b_signal);
# b_signal = np.pad(b_signal, (0, npad), 'constant', constant_values=(0, 0));
# print('pad2');
# print('point0')
Af = fftpack.fft(a_signal);
Bf = fftpack.fft(b_signal);
Ar = Af.conjugate();
Br = Bf.conjugate();
# Ar = -Af.conjugate();
# Br = -Bf.conjugate();
ashiftab = np.argmax(np.abs(fftpack.ifft(Ar * Bf)));
durationsamples = self.getDuration()*B.sampling_rate;
# if(ashiftab>(durationsamples*0.5)):
# ashiftab = ashiftab-durationsamples;
return truediv(ashiftab, B.sampling_rate);
def getBeatEventList(self, time_range = None):
beats = self.getBeats();
if(time_range is None):
return EventList.FromStartTimes(beats, type='beats');
start_beat = 0;
end_beat = len(beats) - 1;
if(time_range[0] is not None):
while((start_beat0 and (beats[end_beat]>time_range[1])):
end_beat = end_beat-1;
if(end_beat>start_beat):
return EventList.FromStartTimes(beats[start_beat:end_beat], type='beats');
else:
return None;
def getBeatEvents(self, start_time=None, end_time=None):
beat_eventlist = self.getBeatEventList();
return beat_eventlist.events;
def AudioClip(self, start, end):
from . import AudioClip
clip = AudioClip.AudioClip(path=self.getPath(), start=start, end=end);
return clip;
def getWithSoundAdded(self, add_times, sound=None, mute_original=None, gain_original = None):
if(sound is None):
sound = Audio.PingSound(sampling_rate=self.sampling_rate);
if(sound.sampling_rate==self.sampling_rate):
s_toadd = sound.getSignal();
else:
new_n_samples = self.sampling_rate * sound.getDuration();
s_toadd = sp.signal.resample(sound.getSignal(), int(new_n_samples));
result = self.clone();
if(mute_original):
result.x = np.zeros(result.x.shape);
if(gain_original is not None):
result.x = result.x*gain_original;
sl = len(s_toadd);
for t in add_times:
if(t0.005):
nosc = truediv(math.log(noise_floor,0.5),damping);
n_seconds = truediv(nosc, freq);
else:
n_seconds = 10.0;
x = np.sin(np.linspace(0, n_seconds * freq * 2 * np.pi, np.round(n_seconds * sampling_rate)));
dmp = np.linspace(0, n_seconds * freq, np.round(n_seconds * sampling_rate))
dmp = np.power(0.5, dmp * damping);
return np.multiply(x, dmp);
@staticmethod
def PingSound(n_seconds=None, freqs=None, damping=None, sampling_rate = 16000):
if(freqs is None):
# freqs = [400,500,600, 700, 800, 900, 1000, 1100, 1200, 1300];
# freqs = np.arange(4, 25) * 100
freqs = np.arange(5, 25) * 75; # just kind of thought this sounded fine...
if(damping is None):
damping = [0.05]*len(freqs);
if(not isinstance(damping,list)):
damping = [damping]*len(freqs);
s = Audio._getDampedSin(freq=freqs[0], n_seconds = n_seconds, sampling_rate = sampling_rate, damping=damping[0]);
for h in range(1,len(freqs)):
new_s = Audio._getDampedSin(freq=freqs[h], n_seconds = n_seconds, sampling_rate = sampling_rate, damping=damping[h]);
if(len(new_s)>len(s)):
new_s[:len(s)]=new_s[:len(s)]+s;
s = new_s;
else:
s[:len(new_s)] = s[:len(new_s)]+new_s;
sa = Audio(x=s, sampling_rate=sampling_rate, name = 'ping');
# sa.setValueRange(value_range=[-1,1]);
sa.setMaxAbsValue(1.0);
return sa;
##### --- FEATURES --- #####
def getBeats(self, use_full_signal=True, tightness = None, force_recompute=False):
"""
:param use_full_signal: If called from AudioClip class, this will determine whether the full signal is used or
just the clip. This is important because the tempo is a global property. More evidence for a constant tempo
is good, but if the tempo changes over the audio you probably don't want to use the full signal.
:param tightness: How tightly to the tempo are beats picked. Must be positive. 0 would not care about tempo.
100 is default. This is actually part of the penalty used in the dynamic programming objective from
Ellis 2007. In librosa: txwt = -tightness * (np.log(-window / period) ** 2)
:param force_recompute:
:return:
"""
if ((not self.hasFeature(name='beats')) or force_recompute):
beat_args = dict(sr = self.sampling_rate, units = 'time');
if (use_full_signal):
beat_args.update(dict(y = self.getFullSignal()));
else:
beat_args.update(dict(y=self.getSignal()))
if (tightness is not None):
beat_args.update(dict(tightness=tightness));
# print(beat_args)
tempo, beats = librosa.beat.beat_track(**beat_args);
self.setFeature(name='tempo', value=tempo);
self.setFeature(name='beats', value=beats);
return self.getFeature(name='beats');
def getBeatVector(self, vector_length=None, force_recompute=False):
"""use_full_signal only makes a difference in AudioClip subclass."""
if ((not self.hasFeature(name='beatvector')) or force_recompute):
D = self.getDuration();
if (vector_length is None):
vector_length = int(math.ceil(D * 240));
rvec = np.zeros(vector_length);
beats = self.getFeature('beats');
step = truediv(D, vector_length);
for i in range(len(beats)):
b = beats[i];
id = int(truediv(b, step));
rvec[id] = 1;
self.setFeature(name='beatvector', value=rvec);
return self.getFeature(name='beatvector');
def getOnsets(self, use_full_signal=True, force_recompute=False, **kwargs):
"""use_full_signal only makes a difference in AudioClip subclass."""
if ((not self.hasFeature(name='onsets')) or force_recompute):
if (use_full_signal):
onsets = librosa.onset.onset_detect(y=self.getFullSignal(), sr=self.sampling_rate, units='time',
**kwargs);
self.setFeature(name='onsets', value=onsets);
else:
onsets = librosa.onset.onset_detect(y=self.getSignal(), sr=self.sampling_rate, units='time',
**kwargs);
self.setFeature(name='onsets', value=onsets);
return self.getFeature(name='onsets');
def getOnsetSamplingRate(self):
return np.true_divide(self.sampling_rate, AUDIO_DEFAULT_HOP_LENGTH);
def pickOnsets(self, pre_max_time=0.03,
post_max_time=0.0,
pre_avg_time=0.1,
post_avg_time=0.1,
wait_time=0.03,
delta=0.07,
force_recompute=True, **kwargs):
"""
:param pre_max_time:
:param post_max_time:
:param pre_avg_time:
:param post_avg_time:
:param wait_time:
:param force_recompute:
:param kwargs:
:return:
"""
# kwargs.setdefault('pre_max', 0.03 * sr // hop_length) # 30ms
# kwargs.setdefault('post_max', 0.00 * sr // hop_length + 1) # 0ms
# kwargs.setdefault('pre_avg', 0.10 * sr // hop_length) # 100ms
# kwargs.setdefault('post_avg', 0.10 * sr // hop_length + 1) # 100ms
# kwargs.setdefault('wait', 0.03 * sr // hop_length) # 30ms
# kwargs.setdefault('delta', 0.07)
pick_params = dict(
pre_max_time=pre_max_time,
post_max_time=post_max_time,
pre_avg_time=pre_avg_time,
post_avg_time=post_avg_time,
wait_time=wait_time,
delta=delta,
)
tp_keys = list(pick_params.keys());
for p in tp_keys:
pick_params[p] = int(round(self.getOnsetSamplingRate() * pick_params[p]));
dparams = dict(
pre_max=pick_params['pre_max_time'],
post_max=pick_params['post_max_time'] + 1,
pre_avg=pick_params['pre_avg_time'],
post_avg=pick_params['post_avg_time'] + 1,
wait=pick_params['wait_time'],
delta=delta
)
return self.getOnsets(force_recompute=force_recompute, **dparams);
def getEvents(self):
return self.getBeatEvents();
def getEventList(self):
return EventList(self.getBeatEvents());
def getOnsetEvents(self):
onsets = self.getOnsets();
events = Event.FromStartTimes(onsets, type='onsets');
return events;
def getBeatEvents(self, start_time=None, end_time=None, **kwargs):
beats = self.getBeats(**kwargs);
start_beat = 0;
end_beat = len(beats) - 1;
if(start_time is not None):
while((start_beat0 and (beats[end_beat]>end_time)):
end_beat = end_beat-1;
if(end_beat>start_beat):
return Event.FromStartTimes(beats[start_beat:end_beat], type='beats');
else:
return None;
def getOnsetEnvelope(self, use_full_signal=True, force_recompute=False, centering=True, **kwargs):
"""use_full_signal only makes a difference in AudioClip subclass."""
feature_name = 'onset_envelope';
if((not self.hasFeature(name=feature_name)) or force_recompute):
if(use_full_signal):
eval_sig = self.getFullSignal();
else:
eval_sig = self.getSignal();
onsets = librosa.onset.onset_strength(y=eval_sig, sr=self.sampling_rate, centering=centering, hop_length=AUDIO_DEFAULT_HOP_LENGTH, **kwargs);
self.setFeature(name=feature_name, value=onsets);
return self.getFeature(name=feature_name);
def getMelSpectrogram(self, n_mels = 128, force_recompute=False):
feature_name = 'melspectrogram';
if((not self.hasFeature(name=feature_name)) or force_recompute):
params = dict( sr = self.sampling_rate,
n_mels = n_mels);
Spec = librosa.feature.melspectrogram(self.getSignal(), **params);
self.setFeature(name=feature_name, value=librosa.power_to_db(Spec, ref=np.max), params=params);
return self.getFeature(feature_name);
def getSpectrogram(self, hop_length=None, force_recompute=False, **kwargs):
feature_name = 'spectrogram';
if((not self.hasFeature(name=feature_name)) or force_recompute):
# params = dict( sr = self.sampling_rate);
# params.update(kwargs);
params = dict(kwargs);
if(hop_length is None):
hop_length = AUDIO_DEFAULT_HOP_LENGTH;
params['hop_length'] = hop_length;
center = kwargs.get('center');
if(center is None):
center = True;
params['center'] = center;
# print('recomputing {}'.format(hop_length))
S = np.abs(librosa.stft(self.getSignal(), **params));
self.setFeature(name=feature_name, value=S, params=params);
return self.getFeature(feature_name);
def getRMSE(self, force_recompute=False, hop_length=None, frame_length=None):
feature_name = 'rmse';
if((not self.hasFeature(name=feature_name)) or force_recompute):
if(frame_length is None):
frac_of_second = 0.05;
frame_length=max(1, int(self.sampling_rate*frac_of_second));
if(hop_length is None):
hop_length=int(math.floor(frame_length*0.5));
params = dict( hop_length = hop_length,
center = True,
frame_length = frame_length);
rmse = librosa.feature.rmse(y=self.getSignal(), **params);
self.setFeature(name=feature_name, value=np.ndarray.flatten(rmse), params=params);
return self.getFeature(feature_name);
def getBeatTimeBefore(self, t):
return self.getBeatBefore(t=t).start;
def getBeatBefore(self, t):
beats = self.getBeatEvents();
bi = self.getBeatIndexBefore(t=t);
return beats[bi].start;
def getBeatIndexBefore(self, t):
beats = self.getBeatEvents();
for i, b in enumerate(beats):
if(b.start>t):
return i-1;
return len(beats)-1;
def getTempogram(self, window_length=None, force_recompute=None, frame_rate=None, resample_rate = None, **kwargs):
"""
:param self:
:param window_length: in seconds
:param force_recompute:
:param kwargs:
:return:
"""
feature_name = 'tempogram';
if ((not self.hasFeature(feature_name)) or force_recompute):
if (window_length is None):
window_length = DEFAULT_TEMPOGRAM_WINDOW_SECONDS;
tpgparams = {};
tpgparams.update(kwargs);
sr = self.sampling_rate;
y=self.getSignal();
if(resample_rate is None):
resample_rate = 22050;
if(sr>resample_rate):
print(("resampling {}Hz to {}Hz".format(sr, resample_rate)));
y = librosa.core.resample(y, orig_sr=sr, target_sr=resample_rate);
sr = resample_rate;
print("resampled")
if(frame_rate is None):
frame_rate = 30;
hop_length = int(round(truediv(sr,frame_rate)));
win_length = int(round(window_length * frame_rate));
tparams = dict(y=y,
sr=sr,
hop_length=hop_length,
win_length=win_length,
**kwargs);
tpgparams.update(dict(sr=sr,hop_length=hop_length, win_length=win_length));
result = librosa.feature.tempogram(**tparams);
###########
tempo_bpms = librosa.tempo_frequencies(result.shape[0], hop_length=hop_length, sr=sr)
self.setFeature(name='tempogram_bpms', value=tempo_bpms);
self.setFeature(name=feature_name, value=result, params=tpgparams);
self.setInfo(label='tempogram_params',value=tpgparams);
return self.getFeature(feature_name);
def plotTempogram(self, window=None, time_range=None, **kwargs):
tempogram = self.getFeature('tempogram', force_recompute=True);
tparams = self.getInfo('tempogram_params')
toshow = tempogram;
if(window is not None):
wstart=int(round(window[0]*self.sampling_rate));
wend = int(round(window[1]*self.sampling_rate));
toshow = tempogram[:,wstart:wend];
mplt = librosa.display.specshow(toshow, sr=tparams['sr'], hop_length=tparams['hop_length'], x_axis = 'time', y_axis = 'tempo')
plt.legend(frameon=True, framealpha=0.75)
plt.set_cmap('coolwarm')
plt.colorbar(format='%+2.0f dB')
if (time_range is not None):
plt.xlim(time_range);
plt.xlabel('Time (s)')
plt.title('Audio Tempogram');
plt.tight_layout()
return mplt;
def plotOnsets(self, **kwargs):
signal = self.getFeature('onset_envelope');
events = self.getOnsetEvents();
mplt = Event.PlotSignalAndEvents(signal, sampling_rate=self.getOnsetSamplingRate(), events=events, **kwargs);
plt.xlabel('Time (s)')
plt.ylabel('Onset Strength')
return mplt;
def plotBeats(self, **kwargs):
signal = self.getFeature('onset_envelope');
events = self.getBeatEvents();
mplt = Event.PlotSignalAndEvents(signal, sampling_rate=self.getOnsetSamplingRate(), events=events, **kwargs);
plt.title('Onset Envelope and Beats');
plt.xlabel('Time (s)')
plt.ylabel('Onset Strength')
return mplt;
def plotOnsetEnvelope(self, **kwargs):
signal = self.getFeature('onset_envelope');
events = None;
mplt = Event.PlotSignalAndEvents(signal, sampling_rate=self.getOnsetSamplingRate(), events=events, **kwargs);
plt.title('Onset Envelope');
plt.xlabel('Time (s)')
plt.ylabel('Onset Strength')
return mplt;
def plotSignal(self, time_range=None, ylim=None, **kwargs):
signal = self.getSignal();
# Event.PlotSignalAndEvents(signal, sampling_rate=self.getOnsetSamplingRate(), events=events, **kwargs);
times = np.arange(len(signal));
times = times * truediv(1.0, self.sampling_rate);
mplt = plt.plot(times, signal);
if (time_range is not None):
plt.xlim(time_range[0], time_range[1])
if (ylim is not None):
plt.ylim(ylim);
plt.title('Time Signal');
return mplt;
FEATURE_FUNCS['melspectrogram'] = getMelSpectrogram;
FEATURE_FUNCS['spectrogram'] = getSpectrogram;
FEATURE_FUNCS['rmse'] = getRMSE;
FEATURE_FUNCS['beats'] = getBeats;
FEATURE_FUNCS['onsets'] = getOnsets;
FEATURE_FUNCS['beatvector'] = getBeatVector;
FEATURE_FUNCS['tempogram'] = getTempogram;
FEATURE_FUNCS['onset_envelope'] = getOnsetEnvelope;
def _make_wav(data, rate):
""" Transform a numpy array to a PCM bytestring """
import struct
from io import BytesIO
import wave
try:
import numpy as np
data = np.array(data, dtype=float)
if len(data.shape) == 1:
nchan = 1
elif len(data.shape) == 2:
# In wave files,channels are interleaved. E.g.,
# "L1R1L2R2..." for stereo. See
# http://msdn.microsoft.com/en-us/library/windows/hardware/dn653308(v=vs.85).aspx
# for channel ordering
nchan = data.shape[0]
data = data.T.ravel()
else:
raise ValueError('Array audio input must be a 1D or 2D array')
scaled = np.int16(data / np.max(np.abs(data)) * 32767).tolist()
except ImportError:
# check that it is a "1D" list
idata = iter(data) # fails if not an iterable
try:
iter(next(idata))
raise TypeError('Only lists of mono audio are '
'supported if numpy is not installed')
except TypeError:
# this means it's not a nested list, which is what we want
pass
maxabsvalue = float(max([abs(x) for x in data]))
scaled = [int(x / maxabsvalue * 32767) for x in data]
nchan = 1
fp = BytesIO()
waveobj = wave.open(fp, mode='wb')
waveobj.setnchannels(nchan)
waveobj.setframerate(rate)
waveobj.setsampwidth(2)
waveobj.setcomptype('NONE', 'NONE')
waveobj.writeframes(b''.join([struct.pack(' len(self.x)):
self.clipped = np.concatenate((np.zeros(int(endsample - len(self.x))), self.clipped));
def resample(self, sampling_rate):
Audio.resample(self, sampling_rate);
self._pull_clip_potion();
def initializeBlank(self):
Audio.initializeBlank(self);
self.start = None;
self.end = None;
self.resampled = None;
self.clipped = None;
def getSignal(self, resample=False):
if(self.resampled):
return self.resampled;
if(resample):
assert(False), "haven't implemented audio clip resampling yet.";
return self.clipped
================================================
FILE: src/video2npz/visbeat3/visbeat3/Event.py
================================================
from .VisBeatImports import *
class Event(AObject):
"""Event (class): An event in time, either in video or audio
Attributes:
start: when the event starts
"""
DIRECTION_FORWARD = 1;
DIRECTION_BACKWARD = -1;
DIRECTION_BOTH = 0;
_EVENT_PHASE_BASE_RES = 8;
def AOBJECT_TYPE(self):
return 'Event';
def __str__(self):
return str(self.getAttributeDict());
def __init__(self, start=None, type=None, weight=None, index=None, is_active=1, unrolled_start = None, direction=0, **kwargs):
AObject.__init__(self, path=None);
self.start = start;
self.type=type;
self.weight=weight;
self.index = index;
self.unrolled_start = unrolled_start;
self.is_active = is_active;
self.direction = direction;
self.a_info.update(kwargs);
def initializeBlank(self):
AObject.initializeBlank(self);
self.start = None;
self.type = None;
self.weight = None;
self.index = None;
self.unrolled_start = None;
self.is_active = None;
self.direction = None;
def getAttributeDict(self):
d = dict();
d['start'] = self.start;
d['type'] = self.type;
d['weight'] = self.weight;
d['index'] = self.index;
d['unrolled_start'] = self.unrolled_start;
d['is_active'] = self.is_active;
d['direction'] = self.direction;
return d;
def toDictionary(self):
d=AObject.toDictionary(self);
d.update(self.getAttributeDict());
return d;
def initAttributesFromDictionary(self, d):
self.start = d['start'];
self.type = d.get('type');
self.weight = d.get('weight');
self.index = d['index'];
self.unrolled_start = d.get('unrolled_start');
self.is_active = d['is_active'];
if (d.get('direction') is None):
self.direction = 0;
else:
self.direction = d['direction'];
def initFromDictionary(self, d):
AObject.initFromDictionary(self, d);
self.initAttributesFromDictionary(d);
def clone(self, start=None):
newe = Event();
newe.initFromDictionary(self.toDictionary());
if (start):
newe.start = start;
return newe;
def _getIsSelected(self):
return self.getInfo('is_selected');
def _setIsSelected(self, is_selected):
self.setInfo('is_selected', is_selected);
def _getPhase(self, phase_resolution=None):
if (self.getInfo('phase') is None):
return -1;
if (phase_resolution is None):
return self.getInfo('phase');
else:
return self.getInfo('phase') * (phase_resolution / Event._EVENT_PHASE_BASE_RES);
def _setPhase(self, phase, phase_resolution):
if (phase_resolution is None):
self.setInfo('phase', phase);
else:
self.setInfo('phase', phase * (Event._EVENT_PHASE_BASE_RES / phase_resolution));
def _getBoundaryType(self):
return self.getInfo('boundary_type');
def _setBoundaryType(self, boundary_type):
self.setInfo('boundary_type', boundary_type);
@classmethod
def _FromGUIDict(cls, gd, phase_resolution=None):
e = cls();
e.initAttributesFromDictionary(gd);
e._setPhase(gd['phase'], phase_resolution=phase_resolution);
e._setBoundaryType(gd.get('boundary_type'));
e._setIsSelected(gd.get('is_selected'));
return e;
@classmethod
def _FromGUIDicts(cls, gds, type=None):
events = [];
for gd in gds:
ne = cls._FromGUIDict(gd);
if (type is not None):
ne.type = type;
events.append(ne);
return events;
def _toGUIDict(self):
'''
note that is_active is switched to 0 or 1 for javascript/json
:return:
'''
d = self.getAttributeDict();
if(self.is_active):
d['is_active'] = 1;
else:
d['is_active'] = 0;
d['phase'] = self._getPhase();
d['boundary_type'] = self._getBoundaryType();
d['is_selected'] = self._getIsSelected();
return d;
@staticmethod
def _ToGUIDicts(events, active=None):
'''
convert to dicts for javascript GUI
:param events:
:param active: if not none, all of the is_active flags will be set to this
:return:
'''
startind = int(round(time.time() * 1000));
starts = [];
for e in range(len(events)):
de = events[e]._toGUIDict();
if (active is not None):
assert (active is 0 or active is 1), "is_active must be 0 or 1";
de['is_active'] = active;
if (de.get('index') is None):
de['index'] = startind + e;
starts.append(de);
return starts;
def getUnrolledStartTime(self):
if(self.unrolled_start is not None):
return self.unrolled_start;
else:
return self.start;
def getStartTime(self):
return self.start;
def getShifted(self, new_start_time):
return Event(self.start-new_start_time, type=self.type, weight=self.weight, index=self.index);
@staticmethod
def GetUnrolledList(event_list, assert_on_folds=None):
out_list = [];
event0 = event_list[0].clone();
event0.unrolled_start = event0.start;
event0.index = 0;
out_list.append(event0);
for e in range(1,len(event_list)):
newe = event_list[e].clone();
if(assert_on_folds):
assert(newe.start>=out_list[-1].start), 'FOLD (non-monotonic event list) DETECTED WHEN NOT ALLOWED!!!\n see Event.GetUnrolledList'
newe.unrolled_start = out_list[-1].unrolled_start+np.fabs(newe.start-out_list[-1].start);
newe.index = e;
out_list.append(newe);
return out_list;
@staticmethod
def NewFromIndices(event_list, inds):
out_list = [];
for ei in inds:
out_list.append(event_list[ei].clone());
return out_list;
@staticmethod
def RollToNOld(events, n_out, momentum = 0.25):
inds = [0];
step = 1;
n_events = len(events);
for b in range(1,n_out):
lastind = inds[-1];
if ((n_out-b)<(n_events-lastind) or lastind==0):
inds.append(lastind+1);
step = 1;
elif(lastind==(len(events)-1)):
inds.append(len(events)-2);
step = -1;
else:
foreward_p = 0.5+momentum;
roll = np.random.rand();
if(roll-1):
lastf = 0;
for ei in range(1,len(events)):
links.append({});
links[ei]['prev_f']=lastf;
links[ei]['prev_b']=lastb;
lastbu = lastb;
lastfu = lastf;
if(lastbu is None):
lastbu = 0;
if(lastfu is None):
lastfu = 0;
if(events[ei].direction<1):
for lb in range(lastbu,ei):
links[lb]['next_b']=ei;
# print("ei is {} and lastbu is {}, lastb is {}".format(ei, lastbu, lastb));
lastb = ei;
if (events[ei].direction>-1):
for lf in range(lastfu, ei):
links[lf]['next_f'] = ei;
# print("ei is {} and lastfu is {}, lastf is {}".format(ei, lastfu, lastf));
lastf = ei;
return links;
@staticmethod
def RollToN(events, n_out, start_index = 0, momentum=0.1):
links = Event.GetDirectedLinks(events);
inds = [start_index];
step = 1;
n_events = len(events);
for b in range(1, n_out):
lastind = inds[-1];
foreward_p = 0.5 + momentum;
roll = np.random.rand();
if (roll < foreward_p):
step = step;
else:
step = -step;
if(links[lastind].get('prev_b') is None):
step = 1;
if(links[lastind].get('next_f') is None):
step = -1;
if(step>0):
inds.append(links[lastind]['next_f']);
else:
inds.append(links[lastind]['prev_b']);
# print(inds);
return Event.GetUnrolledList(Event.NewFromIndices(events, inds));
@staticmethod
def Clone(event_list):
out_list = [];
for ei in event_list:
out_list.append(ei.clone());
return out_list;
@staticmethod
def SetDirections(event_list, direction):
for e in range(len(event_list)):
event_list[e].direction = direction;
return event_list;
@classmethod
def FromStartTimes(cls, starts, type=None):
events = [];
for s in starts:
events.append(cls(start=s, type=type));
return events;
@classmethod
def FromStartsAndWeights(cls, starts, weights, type=None):
events = [];
assert(len(starts)==len(weights)), 'Event.FromStartsAndWeights got {} starts and {} weights'.format(len(starts), len(weights));
for s in range(len(starts)):
events.append(cls(start=starts[s], weight=weights[s],type=type));
return events;
@staticmethod
def ToStartTimes(events):
starts = np.zeros(len(events));
for e in range(len(events)):
starts[e]=events[e].start;
return starts;
@staticmethod
def ToWeights(events):
weights = np.zeros(len(events));
for e in range(len(events)):
weights[e] = events[e].weight;
return weights;
#endpoint is false if events are already placed at beginning and end
@staticmethod
def RepeatToLength(events, n, endpoints=False):
if(n=0 and newi=0):
T_out.append(target_events[e]);
S_out.append(source_events[s_out_inds[e]]);
return S_out, T_out;
@staticmethod
def Sort(event_list, func=None):
assert(func is None or func=='start' or func=='time'), "have not implemented sort by {}".format(func);
event_list.sort(key=lambda x: x.start);
return event_list;
@staticmethod
def GetSorted(event_list, func=None):
clone = Event.Clone(event_list);
Event.Sort(clone, func=func);
return clone;
@staticmethod
def GetWithTwoWayMerged(event_list, merge_window = 0.1):
event_list_sorted = Event.GetSorted(event_list);
new_events = [];
new_events.append(event_list_sorted[0].clone());
for ei in range(1,len(event_list_sorted)):
thise = event_list_sorted[ei];
if((thise.start-new_events[-1].start)254):
self.data = self.data.astype(np.int);
def nChannels(self):
if(len(self.data.shape)<3):
return 1;
else:
return self.data.shape[2];
def getClone(self):
rimg = Image(path=self.a_info.get('file_path'), data=self.data.copy());
return rimg;
def getGridPixel(self,x,y,repeatEdge=0):
xo = x;
yo = y;
blackedge = np.zeros(1);
if(len(self.data.shape)==3):
blackedge = np.zeros(self.data.shape[2])
if(y>=self.data.shape[0]):
if(repeatEdge==1):
yo = self.data.shape[0]-1
else:
return blackedge
if(y<0):
if(repeatEdge==1):
yo = 0
else:
return blackedge
if(x>=self.data.shape[1]):
if(repeatEdge==1):
xo=self.data.shape[1]-1
else:
return blackedge
if(x<0):
if(repeatEdge==1):
xo = 0
else:
return blackedge
return self.data[yo,xo]
def getPixel(self, x, y, repeatEdge=0):
if(isinstance(y,int) and isinstance(x,int)):
return self.getGridPixel(x,y)
else:
yf = int(np.floor(y))
yc = int(np.ceil(y))
xf = int(np.floor(x))
xc = int(np.ceil(x))
print('getting here?')
print(xf);
print(yf);
tl = self.getGridPixel(xf,yf,repeatEdge)
tr = self.getGridPixel(xc,yf,repeatEdge)
bl = self.getGridPixel(xf,yc,repeatEdge)
br = self.getGridPixel(xc,yc,repeatEdge)
yalpha = y-yf
xalpha = x-xf
topL = tr*xalpha+tl*(1.0-xalpha)
botL = br*xalpha+bl*(1.0-xalpha)
retv = botL*yalpha+topL*(1.0-yalpha)
return retv
def getShape(self):
return np.asarray(self.data.shape)[:];
def getScaled(self, shape=None, shape_xy=None):
shapeis = (shape is not None);
shapexyis = (shape_xy is not None);
assert((shapeis or shapexyis) and not (shapeis and shapexyis)), "Must provide only one of shape or shape_xy for Image.getScaled"
if(shapeis):
sz=[shape[0], shape[1], self.data.shape[2]];
else:
sz=[shape_xy[1],shape_xy[0],self.data.shape[2]];
imK = sp.misc.imresize(self.data, size=sz);
return Image(data=imK);
def getRotated(self, theta):
imR = sp.misc.imrotate(self.data, theta);
return Image(data=imR);
# def splatAtPixCoord(self, im, location=[0,0]):
# self.data[location[0]:(location[0]+im.data.shape[0]), location[1]:(location[1]+im.data.shape[1]),:]=im.data;
def _splatAtPixCoord(self, im, location=[0,0], **kwargs):
is_int = self._is_int;
selftype = self.dtype;
region0 = [location[0], (location[0]+im.data.shape[0])];
region1 = [location[1], (location[1]+im.data.shape[1])];
if(im.n_channels<4):
self.data[region0[0]:region0[1], region1[0]:region1[1],:]=im.data;
return;
if(im.n_channels == 4):
alphamap = np.moveaxis(np.tile(im._pixels_float[:, :, 3], (3, 1, 1)), [0], [2]);
blenda = (im._pixels_float[:, :, :3]) * alphamap + self._pixels_float[region0[0]:region0[1], region1[0]:region1[1],:]*(1.0 - alphamap);
if(is_int):
blenda = (blenda*255).astype(selftype);
self.data[region0[0]:region0[1], region1[0]:region1[1], :] = blenda;
def reflectY(self):
self.data[:,:,:]=self.data[::-1,:,:];
def reflectX(self):
self.data[:,:,:]=self.data[:,::-1,:];
def PIL(self):
return PIM.fromarray(np.uint8(self.data));
def getRGBData(self):
return self.data[:,:,0:3];
def normalize(self, scale=1.0):
self.data = self.data/np.max(self.data.ravel());
self.data = self.data*scale;
def show(self, new_figure = True):
if(ISNOTEBOOK):
if(new_figure):
plt.figure();
if(self.nChannels()==1):
plt.imshow(self.PIL(), cmap='gray');
else:
plt.imshow(self.PIL());#divided by 255
plt.axis('off');
else:
self.PIL().show();
def writeToFile(self, out_path):
self.PIL().save(out_path);
def getEncodedBase64(self):
return base64.b64encode(self.data);
def getDataAsString(self):
return self.data.tostring();
@staticmethod
def FromBase64(encoded_data, shape):
d = base64.decodestring(encoded_data);
npar = np.frombuffer(d, dtype=np.float64);
rIm = Image(data=np.reshape(npar, shape));
return rIm;
@staticmethod
def FromDataString(data_string, shape, dtype=None):
if(dtype is None):
dtype=np.float64;
img_1d = np.fromstring(data_string, dtype=dtype);
reconstructed_img = img_1d.reshape((height, width, -1))
###########################adapted from https://gist.github.com/turicas/1455973##########################
def _get_font_size(self, text, font_path, max_width=None, max_height=None):
if max_width is None and max_height is None:
raise ValueError('You need to pass max_width or max_height')
font_size = 1
text_size = self.get_text_size(font_path, font_size, text)
if (max_width is not None and text_size[0] > max_width) or (max_height is not None and text_size[1] > max_height):
raise ValueError("Text can't be filled in only (%dpx, %dpx)" % text_size)
while True:
if (max_width is not None and text_size[0] >= max_width) or (max_height is not None and text_size[1] >= max_height):
return font_size - 1
font_size += 1
text_size = self.get_text_size(font_path, font_size, text)
def writeOutlinedText(self, xy, text,
font_size=11,
max_width=None,
max_height=None,
encoding='utf8', draw_context = None):
self.writeText(xy=[xy[0]+3, xy[1]+3], text=text, font_filename='RobotoCondensed-Regular.ttf',
font_size=font_size,
max_width=max_width,
color=(0, 0, 0),
max_height=max_height,
encoding=encoding, draw_context=draw_context);
self.writeText(xy=xy, text=text, font_filename='RobotoCondensed-Regular.ttf',
font_size=font_size,
max_width=max_width,
color=(255, 255, 255),
max_height=max_height,
encoding=encoding, draw_context=draw_context);
def writeText(self, xy, text, font_filename='RobotoCondensed-Regular.ttf',
font_size=11,
color=(0, 0, 0),
max_width=None,
max_height=None,
encoding='utf8', draw_context = None):
x=xy[0];
y=xy[1];
font_paths = find_all_files_with_name_under_path(name=font_filename,
path=os.path.dirname(os.path.abspath(__file__)));
font_path = font_paths[0];
if isinstance(text, str):
text = text.decode(encoding)
if font_size == 'fill' and (max_width is not None or max_height is not None):
font_size = self._get_font_size(text, font_path, max_width,
max_height)
text_size = self._get_text_size(font_path, font_size, text)
font = ImageFont.truetype(font=font_path, size=font_size);
# font = ImageFont.truetype(font_filename, font_size)
if x == 'center':
x = (self.data.shape[1] - text_size[0]) / 2
if y == 'center':
y = (self.data.shape[0] - text_size[1]) / 2
if(draw_context is None):
ipil = self.PIL();
draw = ImageDraw.Draw(ipil)
draw.text((x, y), text, font=font, fill=color)
datashape = self.data.shape;
self.data = np.array(ipil.getdata());
self.data.shape = datashape;
else:
draw_context.text((x, y), text, font=font, fill=color);
return text_size
def _get_text_size(self, font_path, font_size, text):
font = ImageFont.truetype(font_path, font_size)
return font.getsize(text)
@staticmethod
def _VBMark():
if(Image._VBMRK is None):
Image._VBMRK = Image(path=GetVBMarkPath());
return Image._VBMRK;
def _vbmark(self):
self._splatAtPixCoord(**self._vbmarker());
def _vbmarker(self):
vbm = Image._VBMark();
wmfrac = min(VBMARK_SIZE * self.width, VBMARK_SIZE * self.height);
scaleval = min(1.0, np.true_divide(wmfrac, vbm.width));
if (scaleval < 1.0):
vbms = vbm.getScaled(shape=[int(vbm.shape[0] * scaleval), int(vbm.shape[1] * scaleval), vbm.shape[2]]);
else:
vbms = vbm.clone();
margin = min(vbm.width, vbm.height, int(VBMMARGIN * self.width), int(VBMMARGIN * self.height));
return dict(im=vbms, location=[self.height - vbms.height - margin, self.width - vbms.width - margin]);
def writeTextBox(self, xy, text, box_width, font_filename='RobotoCondensed-Regular.ttf',
font_size=11, color=(0, 0, 0), place='left',
justify_last_line=False):
x = xy[0];
y = xy[1];
font_paths = find_all_files_with_name_under_path(name=font_filename,
path=os.path.dirname(os.path.abspath(__file__)));
font_path = font_paths[0];
lines = []
line = []
words = text.split()
for word in words:
new_line = ' '.join(line + [word])
size = self._get_text_size(font_path, font_size, new_line)
text_height = size[1]
if size[0] <= box_width:
line.append(word)
else:
lines.append(line)
line = [word]
if line:
lines.append(line)
lines = [' '.join(line) for line in lines if line]
height = y
for index, line in enumerate(lines):
height += text_height
if place == 'left':
self.writeText((x, height), line,
font_filename,
font_size,
color)
elif place == 'right':
total_size = self._get_text_size(font_path, font_size, line)
x_left = x + box_width - total_size[0]
self.writeText((x_left, height), line, font_filename,
font_size, color)
elif place == 'center':
total_size = self._get_text_size(font_path, font_size, line)
x_left = int(x + ((box_width - total_size[0]) / 2))
self.writeText((x_left, height), line,
font_filename,
font_size, color)
elif place == 'justify':
words = line.split()
if (index == len(lines) - 1 and not justify_last_line) or len(words) == 1:
self.writeText((x, height), line,
font_filename,
font_size,
color)
continue
line_without_spaces = ''.join(words)
total_size = self._get_text_size(font_path, font_size,
line_without_spaces)
space_width = (box_width - total_size[0]) / (len(words) - 1.0)
start_x = x
for word in words[:-1]:
self.writeText((start_x, height), word,
font_filename,
font_size, color)
word_size = self._get_text_size(font_path, font_size,
word)
start_x += word_size[0] + space_width
last_word_size = self._get_text_size(font_path, font_size,
words[-1])
last_word_x = x + box_width - last_word_size[0]
self.writeText((last_word_x, height), words[-1],
font_filename,
font_size, color)
return (box_width, height - y)
#####################################################
from . import Image_CV
if(Image_CV.USING_OPENCV):
Image.USING_OPENCV = Image_CV.USING_OPENCV;
Image.RGB2Gray=Image_CV.RGB2Gray;
Image.GrayToRGB=Image_CV.Gray2RGB;
Image.cvGoodFeaturesToTrack=Image_CV.cvGoodFeaturesToTrack;
Image.withFlow=Image_CV.withFlow;
cvDenseFlowFarneback = Image_CV.cvDenseFlowFarneback;
# Image. = Image_CV.
# Image. = Image_CV.
# Image. = Image_CV.
# Image. = Image_CV.
# Image. = Image_CV.
ocv = Image_CV.ocv;
================================================
FILE: src/video2npz/visbeat3/visbeat3/Image_CV.py
================================================
#CVFunctions
from .VisBeatImports import *
import numpy as np
import scipy as sp
from PIL import Image as PIM
#from VBObject import *
from . import Image as vbImage
import math
DEFAULT_FLOW_HISTOGRAM_BINS = 8;
USING_OPENCV=True
try:
import cv2 as ocv
except ImportError:
USING_OPENCV=False;
AWARN('OpenCV not installed; not importing Image_CV')
#these are functions that use OpenCV that aren't class functions
if(USING_OPENCV):
def flow2rgb(flow):
h, w = flow.shape[:2]
fx, fy = flow[:,:,0], flow[:,:,1]
ang = np.arctan2(fy, fx) + np.pi
v = np.sqrt(fx*fx+fy*fy)
hsv = np.zeros((h, w, 3), np.uint8)
hsv[...,0] = ang*(180/np.pi/2)
hsv[...,1] = 255
#v=np.minimum(v*4, 255);
v = np.log(v+1);
vmax = np.max(v[:]);
vf=v/vmax;
v=vf*255;
hsv[...,2] = v;#np.minimum(v*4, 255)
rgb = ocv.cvtColor(hsv, ocv.COLOR_HSV2BGR)
return rgb
def showFlowHSV(flow, new_figure = True):
if(ISNOTEBOOK):
#plt.imshow(self.data*0.0039215686274509);#divided by 255
if(new_figure):
plt.figure();
plt.imshow(PIM.fromarray(flow2rgb(flow)));
plt.axis('off');
else:
self.PIL().show();
def cornerHarris(im, blockSize=None, ksize=None, k=None):
if (blockSize is None):
blockSize = 2;
if (ksize is None):
ksize = 3;
if (k is None):
k = 0.04;
return ocv.cornerHarris(im, 2, 3, 0.04);
def cvDenseFlowFarneback(from_image, to_image, pyr_scale=None, levels=None, winsize=None, iterations=None, poly_n=None, poly_sigma=None, flags=None):
"""Can provide numpy arrays or Image objects as input. Returns the flow from->to."""
# params for Farneback's method
from_im=from_image;
to_im=to_image;
from_is_ob = isinstance(from_image, vbImage.Image);
to_is_ob = isinstance(to_image, vbImage.Image)
if(from_is_ob):
if(from_image.nChannels()>1):
from_im=from_image.getClone();
from_im.RGB2Gray();
from_im=from_im.data;
if(to_is_ob):
if(to_image.nChannels()>1):
to_im=to_image.getClone();
to_im.RGB2Gray();
to_im=to_im.data;
inputs = dict( flow = None,
pyr_scale = pyr_scale,
levels = levels,
winsize = winsize,
iterations = iterations,
poly_n = poly_n,
poly_sigma = poly_sigma,
flags=flags);
default_flow=None;
default_pyr_scale=0.5;
default_levels=int(math.log(float(min(to_im.shape)), 2))-4;
default_winsize = 15;
default_iterations=3;
default_poly_n=5;
default_poly_sigma=1.25;
use_params = dict(flow=default_flow,
pyr_scale=default_pyr_scale,
levels=default_levels,
winsize=default_winsize,
iterations=default_iterations,
poly_n=default_poly_n,
poly_sigma=default_poly_sigma,
flags=0);
for key in inputs:
if(inputs[key] is not None):
use_params[key]=inputs[key];
return ocv.calcOpticalFlowFarneback(prev=from_im, next=to_im, **use_params);
# These functions are to add to Image class
if(USING_OPENCV):
def RGB2Gray(self):
if(self.nChannels()==1):
return;
else:
self.data = ocv.cvtColor(self.data, ocv.COLOR_RGB2GRAY);
def Gray2RGB(self):
if(self.nChannels()==1):
self.data = ocv.cvtColor(self.data, ocv.COLOR_GRAY2RGB)
def cvGoodFeaturesToTrack(self, maxCorners=None, qualityLevel=None, minDistance=None, corners=None, mask=None, blockSize=None, useHarrisDetector=None):
assert(self.data is not None), "must provide image to find features";
if(self.nChannels()==1):
gray_image=self.data.copy();
else:
gray_image=ocv.cvtColor(self.data, cv2.COLOR_RGB2GRAY);
argd={};
if(maxCorners is not None):
d['maxCorners']=maxCorners;
if(qualityLevel is not None):
d['qualityLevel']=qualityLevel;
if(minDistance is not None):
d['minDistance']=minDistance;
if(corners is not None):
d['corners']=corners;
if(mask is not None):
d['mask']=mask;
if(blockSize is not None):
d['blockSize']=blockSize;
if(useHarrisDetector is not None):
d['useHarrisDetector']=useHarrisDetector;
return ocv.goodFeaturesToTrack(gray_image, **argd);
def withFlow(self, flow, step=16):
clone = self.getClone();
if(clone.nChannels()<3):
clone.convertToRGB();
img = clone.data;
h, w = img.shape[:2]
y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2,-1).astype(int)
# flow[y, x] is fx, fy
fx, fy = flow[y,x].T
# After vstack, each column: x, y, x+fx, y+fy
# After transpose: each row: x, y, x+fx, y+fy
# After reshape: each row: [[x, y], [x+fx, y+fy]]
lines = np.vstack([x, y, x+fx, y+fy]).T.reshape(-1, 2, 2)
lines = np.int32(lines + 0.5)
ocv.polylines(img, lines, 0, (0, 255, 0), thickness=3)
for (x1, y1), (x2, y2) in lines:
cv2.circle(img, (x1, y1), 1, (0, 255, 0), -1)
return clone
================================================
FILE: src/video2npz/visbeat3/visbeat3/SourceLocationParser.py
================================================
"""
This code was a last minute hack. It works fine enough for parsing youtube urls, but I would use it for any kind of reference.
Based loosely on video backends from django embed video.
"""
import re
import requests
import os
import sys
if sys.version_info.major == 3:
import urllib.parse as urlparse
else:
import urllib.parse
class SourceURL(object):
"""
Modified from django embed video
"""
allow_https = True
is_secure = False
@classmethod
def SourceLocationType(cls):
return cls.__name__;
def __init__(self, source_location):
self.source_location_type = self.SourceLocationType()
self._source_location = source_location
#
@property
def code(self):
"""
unique string to identify file
:return:
"""
return self._getCode();
def _getCode(self):
raise NotImplementedError;
@code.setter
def code(self, value):
self._setCode(value);
def _setCode(self, value):
raise NotImplementedError;
#
@property
def url(self):
"""
URL of video.
"""
return self.get_url()
def get_url(self):
raise NotImplementedError
@property
def protocol(self):
"""
Protocol used to generate URL.
"""
return 'https' if self.allow_https and self.is_secure else 'http'
@property
def thumbnail(self):
"""
URL of video thumbnail.
"""
return self.get_thumbnail_url()
@classmethod
def is_valid(cls, url):
return True if cls.re_detect.match(url) else False
class WebSourceException(Exception):
""" Parental class for all embed_media exceptions """
pass
class VideoDoesntExistException(WebSourceException):
""" Exception thrown if video doesn't exist """
pass
class UnknownBackendException(WebSourceException):
""" Exception thrown if video backend is not recognized. """
pass
class UnknownIdException(VideoDoesntExistException):
"""
Exception thrown if backend is detected, but video ID cannot be parsed.
"""
pass
class YoutubeURL(SourceURL):
"""
for YouTube URLs.
"""
@classmethod
def SourceLocationType(cls):
return 'youtube';
# Compiled regex (:py:func:`re.compile`) to search code in URL.
# Example: ``re.compile(r'myvideo\.com/\?code=(?P\w+)')``
re_code = None
# Compilede regec (:py:func:`re.compile`) to detect, if input URL is valid for current backend.
# Example: ``re.compile(r'^http://myvideo\.com/.*')``
re_detect = None
# Pattern in which the code is inserted.
# Example: ``http://myvideo.com?code=%s``
# :type: str
pattern_url = None
pattern_thumbnail_url = None
re_detect = re.compile(
r'^(http(s)?://)?(www\.|m\.)?youtu(\.?)be(\.com)?/.*', re.I
)
re_code = re.compile(
r'''youtu(\.?)be(\.com)?/ # match youtube's domains
(\#/)? # for mobile urls
(embed/)? # match the embed url syntax
(v/)?
(watch\?v=)? # match the youtube page url
(ytscreeningroom\?v=)?
(feeds/api/videos/)?
(user\S*[^\w\-\s])?
(?P[\w\-]{11})[a-z0-9;:@?&%=+/\$_.-]* # match and extract
''',
re.I | re.X
)
pattern_url = '{protocol}://www.youtube.com/embed/{code}'
pattern_thumbnail_url = '{protocol}://img.youtube.com/vi/{code}/{resolution}'
resolutions = [
'maxresdefault.jpg',
'sddefault.jpg',
'hqdefault.jpg',
'mqdefault.jpg',
]
def get_url(self):
"""
Returns URL folded from :py:data:`pattern_url` and parsed code.
"""
url = self.pattern_url.format(code=self.code, protocol=self.protocol)
url += '?' + self.query.urlencode() if self.query else ''
return url
def get_thumbnail_url(self):
"""
Returns thumbnail URL folded from :py:data:`pattern_thumbnail_url` and
parsed code.
:rtype: str
"""
return self.pattern_thumbnail_url.format(code=self.code,
protocol=self.protocol)
def _getCode(self):
match = self.re_code.search(self._source_location)
if match:
return match.group('code')
parsed_url = urllib.parse.urlparse(self._source_location)
parsed_qs = urllib.parse.parse_qs(parsed_url.query)
if 'v' in parsed_qs:
code = parsed_qs['v'][0]
elif 'video_id' in parsed_qs:
code = parsed_qs['video_id'][0]
else:
raise UnknownIdException('Cannot get ID from `{0}`'.format(self._source_location))
return code
def get_thumbnail_url(self):
"""
Returns thumbnail URL folded from :py:data:`pattern_thumbnail_url` and
parsed code.
:rtype: str
"""
for resolution in self.resolutions:
temp_thumbnail_url = self.pattern_thumbnail_url.format(
code=self.code, protocol=self.protocol, resolution=resolution)
if int(requests.head(temp_thumbnail_url).status_code) < 400:
return temp_thumbnail_url
return None
class FilePathURL(SourceURL):
@classmethod
def SourceLocationType(cls):
return 'file_path';
def __init__(self, source_location):
self.source_location_type = self.SourceLocationType()
self._source_location = source_location;
@classmethod
def is_valid(cls, source_location):
return os.path.isfile(source_location);
def _getCode(self):
name_parts = os.path.splitext(os.path.basename(self._source_location));
return name_parts[0];
SOURCE_LOCATION_TYPES = (
YoutubeURL,
FilePathURL,
)
def ParseSourseLocation(url):
"""
:param url:
:return:
"""
for backend in SOURCE_LOCATION_TYPES:
if backend.is_valid(url):
return backend(url)
raise UnknownBackendException
================================================
FILE: src/video2npz/visbeat3/visbeat3/TimeSignal.py
================================================
from .VBObject import *
from .Event import *
import math
from operator import truediv
from .VisBeatImports import *
class TimeSignal(VBObject):
"""TimeSignal (class): A time signal, and a bunch of convenience functions to go with it.
Attributes:
sampling_rate: the sampling rate
visualizations dictionary of visualizations. (removed - too many dependencies)
"""
def VBBJECT_TYPE(self):
return 'TimeSignal';
def __init__(self, path=None, sampling_rate = None):
VBObject.__init__(self, path=path);
# self.initializeBlank();
# self.visualizations = AFuncDict(owner=self, name='visualizations');
# self.visualizations.functions.update(self.VIS_FUNCS);
if(sampling_rate):
self.sampling_rate=sampling_rate;
def initializeBlank(self):
VBObject.initializeBlank(self);
self.sampling_rate = None;
#
@property
def frame_rate(self):
return self._getFrameRate();
def _getFrameRate(self):
raise NotImplementedError;
#
def getSampleAtTime(self, f):
prev_sample = self.getSampleAtIndex(math.floor(f));
next_sample = self.getSampleAtIndex(math.ceil(f));
sample_progress = f-np.floor(f);
return (next_sample*sample_progress)+(prev_sample*(1.0-sample_progress));
def getSampleAtIndex(self, i):
return self.getTimeForIndex();
def getDuration(self):
assert(False), "getDuration must be implemented for subclass of TimeSignal"
def getSampleDuration(self):
return 1.0/self.sampling_rate;
def getTimeForIndex(self, i):
return i*self.getSampleDuration();
# def toDictionary(self):
# d = VBObject.toDictionary(self);
# assert(False), "haven't implemented toDictionary for {} yet".format(self.VBOBJECT_TYPE())
# #serialize class specific members
# return d;
# def initFromDictionary(self, d):
# VBObject.initFromDictionary(self, d);
# assert(False), "haven't implemented initFromDictionary for {} yet".format(self.VBOBJECT_TYPE())
# #do class specific inits with d;
================================================
FILE: src/video2npz/visbeat3/visbeat3/TimeSignal1D.py
================================================
from .TimeSignal import *
import math
class TimeSignal1D(TimeSignal):
"""TimeSignal1D (class): A time signal, and a bunch of convenience functions to go with it.
Attributes:
sampling_rate: the sampling rate
x: the time signal
"""
def VBOJECT_TYPE(self):
return 'TimeSignal1D';
def __init__(self, path=None, sampling_rate = None, x=None):
TimeSignal.__init__(self, path=path, sampling_rate=sampling_rate);
if(x is not None):
self.x = x;
#self.initializeBlank(); # will be called by parent
def initializeBlank(self):
TimeSignal.initializeBlank(self);#YES KEEP call through weird loops
self.x = None;
def getSignal(self, resampled=False):
return self.x;
def getSignalSegment(self, time_range):
signal = self.getSignal();
seg_start = int(time_range[0]*self.sampling_rate);
seg_end = int(time_range[1]*self.sampling_rate);
return signal[seg_start:seg_end];
def getFullSignal(self):
return self.x;
def getSampleAtTime(self, f):
prev_sample = self.x[int(math.floor(f))];
next_sample = self.x[int(math.ceil(f))];
sample_progress = f-np.floor(f);
return (next_sample*sample_progress)+(prev_sample*(1.0-sample_progress));
def getSampleAtIndex(self, i):
return self.x[i];
def getDuration(self):
return truediv(len(self.getSignal()), self.sampling_rate);
def setValueRange(self, value_range=None):
if(value_range is None):
value_range = [0,1];
data = self.x[:];
currentscale = np.max(data)-np.min(data);
data = (data/currentscale)*(value_range[1]-value_range[0]);
data = data-np.min(data)+value_range[0]
self.x = data;
def setMaxAbsValue(self, max_abs_val=1.0):
data = self.x[:];
currentscale = np.max(np.fabs(data));
data = (data/currentscale)*max_abs_val;
self.x = data;
================================================
FILE: src/video2npz/visbeat3/visbeat3/VBMIDI.py
================================================
# %load VisBeat/MidiParse.py
import mido
import numpy as np
import os
# from TimeSignal1D import *
from .Audio import *
from .Event import *
class VBMIDITrack(object):
def __init__(self, track, ticks_per_beat):
self.mido_track = track;
self.name = track.name;
# print('Track {}: {}'.format(i, track.name));
self.tempo = next((msg.tempo for msg in track if msg.type == 'set_tempo'), None);
self.ticks_per_beat = ticks_per_beat;
# self._get_note_on_times();
self.note_on_times = None;
def getBPM(self):
return mido.tempo2bpm(self.tempo);
def getNoteOnTimes(self, include_negative=None):
if(self.note_on_times is None or (include_negative)):
self._get_note_on_times(include_negative = include_negative);
return self.note_on_times;
def _get_note_on_times(self, include_negative = None):
"""
Gets the starting time of each note.
"""
note_times = []
current_time = 0;
for msg in self.mido_track:
if not msg.is_meta:
delta_time = mido.tick2second(msg.time, self.ticks_per_beat, self.tempo)
current_time += delta_time
if msg.type == 'note_on' and msg.velocity > 0:
if (include_negative or current_time>=0):
note_times.append(current_time);
self.note_on_times = np.array(note_times);
def get_note_durations(self, track_num):
note_durations = []
currently_played_notes = {}
current_time = 0
for msg in self.mido_track:
if not msg.is_meta:
delta_time = mido.tick2second(msg.time, self.ticks_per_beat, self.tempo)
current_time += delta_time
if msg.type == 'note_on' and msg.velocity > 0 and msg.note not in currently_played_notes:
currently_played_notes[msg.note] = current_time
#if len(currently_played_notes) > 1:
# print "Number of played notes have reached: ", len(currently_played_notes)
elif msg.type == 'note_off' or (msg.type == 'note_on' and msg.velocity == 0):
duration = current_time - currently_played_notes[msg.note]
note_durations.append((currently_played_notes[msg.note], duration))
currently_played_notes.pop(msg.note)
assert not bool(currently_played_notes), "Finished looping through all messages. There should not be any notes playing at this point."
#print "before sorting: ", note_durations
note_durations.sort(key=lambda x : x[0])
#print "after sorting: ", note_durations
return np.array([ x[1] for x in note_durations ])
def get_mouth_events(self):
# note_times = []
current_time = 0;
number_on = 0;
events = [];
open_buffer = 0.1;
close_buffer = 0.1
last_type = 0;
events.append(Event(start=0, type='mouth_close', weight=1));
for msg in self.mido_track:
if not msg.is_meta:
delta_time = mido.tick2second(msg.time, self.ticks_per_beat, self.tempo)
current_time += delta_time
last_time = events[-1].start;
passed = current_time-last_time;
if msg.type == 'note_on' and msg.velocity > 0:
if(last_type==0):
if(passed>open_buffer):
events.append(Event(start=current_time-open_buffer, type='mouth_closed', weight=0));
events.append(Event(start=current_time, type='mouth_open', weight = truediv(msg.velocity,127)));
number_on = number_on + 1;
last_type=1;
if(msg.type == 'note_off' or (msg.type=='note_on' and msg.velocity == 0)):
if (last_type == 1):
if (passed > close_buffer):
events.append(Event(start=current_time - close_buffer, type='mouth_opened', weight=0));
events.append(Event(start=current_time, type='mouth_close', weight = truediv(msg.velocity,127)));
number_on = number_on-1;
last_type=0;
# assert(number_on>-1);
# if(number_on==0):
return events;
# self.note_on_times = np.array(note_times);
def getNoteOnTimesAsAudio(self, sampling_rate = None, note_sound=None, n_seconds=None):
assert(n_seconds is not None), "must provide n seconds"
if(sampling_rate is None):
sampling_rate = 16000;
if(note_sound is None):
note_sound = Audio.getPing();
s = Audio.Silence(n_seconds=n_seconds, sampling_rate=sampling_rate, name=self.name)
s = s.getWithSoundAdded(note_sound, self.getNoteOnTimes());
return s;
class VBMIDI(TimeSignal1D):
def __init__(self, path=None):
TimeSignal1D.__init__(self, path=path);
self.midi_file = mido.MidiFile(path)
self.tracks = [];
for i, track in enumerate(self.midi_file.tracks):
self.tracks.append(VBMIDITrack(track, self.midi_file.ticks_per_beat));
def getNoteOnTimes(self, include_negative=None):
return self.tracks[-1].getNoteOnTimes(include_negative=include_negative);
def getMouthEvents(self):
return self.tracks[-1].get_mouth_events();
def getNoteOnTimesAsAudio(self, sampling_rate=None, note_sound=None):
s = self.tracks[-1].getNoteOnTimesAsAudio(sampling_rate = sampling_rate, note_sound = note_sound, n_seconds = self.midi_file.length);
if (s.name is None):
s.name = self.getInfo('file_name')
return s;
================================================
FILE: src/video2npz/visbeat3/visbeat3/VBObject.py
================================================
import os
import json
from .VisBeatImports import *
from .AFuncDict import *
from .AObject import AObject
class VBObject(AObject):
"""VBObject (class): This is a paarent class used to implement common serialization and other functions. There ends
up being three different dictionaries of data.
a_info - for small labels and such. Part of AObject.
a_data - for data to be computed in experiments. I generally use this for things I don't want to automatically
save out to file.
features - these are features tied to the results of functions, and manager classes (e.g. VideoSource) will save
these to disk for future use.
FEATURE_FUNCS is a dictionary mapping the names of features to their corresponding functions.
"""
FEATURE_FUNCS={};
def __init__(self, path=None):
AObject.__init__(self, path=path);
def initializeBlank(self):
AObject.initializeBlank(self);
self.a_info.update({'VBObjectType': self.VBOBJECT_TYPE()});
self.features = AFuncDict(owner=self, name='features');
self.features.functions.update(self.FEATURE_FUNCS);
def saveFeature(self, name, path):
"""Subclasses can implement version of this that will check members for features if those features arent found here."""
return self.features.saveEntry(name=name, path=path);
def saveFeatures(self, path):
return self.features.save(path=path);
def loadFeature(self, name, path):
"""Subclasses can implement version of this that will check whether feature is registered before loading."""
return self.features.loadEntry(name=name, path=path);
def loadFeatures(self, path):
return self.features.load(path=path);
def getFeature(self,name, force_recompute=False, **kwargs):
"""Understood to get the value of a feature. can automatically recompute if feature has registered function."""
params = kwargs;
assert (not kwargs.get('params')), "STILL TRYING TO USE PARAMS INSTEAD OF KWARGS. FIX THIS";
return self.features.getValue(name=name, params=kwargs, force_recompute=force_recompute);
def getFeatureEntry(self, name, params=None, force_recompute=False):
return self.features.getEntry(name=name, params=params, force_recompute=force_recompute);
def getFeatureParams(self, name):
return self.features.getParams(name=name);
def setFeature(self, name, value, params=None):
rval = self.features.setEntry(name=name, d=dict(value=value, params=params));
self.features.setEntryModified(name=name, is_modified=True);
return rval;
def removeFeature(self, name, assert_if_absent=True, set_modified=True):
self.features.removeEntry(name=name, assert_if_absent=assert_if_absent, set_modified=set_modified);
def hasFeature(self, name):
"""Just checks to see if it's there."""
return self.features.hasEntry(name=name);
def getFeatureFunction(self, feature_name):
return self.features.getFunction(name=feature_name);
def getFeaturesList(self):
return self.features.getKeyList();
def getFeatureFunctionsList(self):
return self.features.getFunctionList();
def clearFeatureFiles(self, features_to_clear=None, **kwargs):
if(self.clear_feature_files_func):
self.clear_feature_files_func(self, features_to_clear=features_to_clear, **kwargs);
else:
VBWARN("CLEAR FEATURE FILES FUNCTION HAS NOT BEEN PROVIDED FOR {} INSTANCE".format(self.VBOBJECT_TYPE()));
########### VIRTUAL FUNCTIONS #############
def AOBJECT_TYPE(self):
return 'VBObject';
def VBOBJECT_TYPE(self):
return self.AOBJECT_TYPE();
# ##Example of how these functions should be written ina subclass, for 'AssetManager' class
# def VBOBJECT_TYPE(self):
# return 'AssetManager';
#
# def toDictionary(self):
# d = VBObject.toDictionary(self);
# #serialize class specific members
# return d;
#
# def initFromDictionary(self, d):
# VBObject.initFromDictionary(self, d);
# #do class specific inits with d;
================================================
FILE: src/video2npz/visbeat3/visbeat3/Video.py
================================================
#VideoVersion#from VisBeatImports import *
from .AObject import *
from .TimeSignal import *
from .Audio import *
from .Warp import *
from .Image import *
import moviepy.editor as mpy
from moviepy.audio.AudioClip import AudioArrayClip as MPYAudioArrayClip
import sys
import math
from operator import truediv
def MPYWriteVideoFile(mpyclip, filename, **kwargs):
temp_audio_filename = get_temp_file_path(final_file_path='TEMP_'+filename+'.m4a', temp_dir_path=Video.VIDEO_TEMP_DIR);
return mpyclip.write_videofile(filename=filename, temp_audiofile= temp_audio_filename, audio_codec='aac', **kwargs);
class Video(TimeSignal):
"""Video (class): A video, and a bunch of convenience functions to go with it.
Attributes:
"""
VIDEO_TEMP_DIR = './'
FEATURE_FUNCS = TimeSignal.FEATURE_FUNCS.copy();
def AOBJECT_TYPE(self):
return 'Video';
def __init__(self, path=None, name=None, num_frames_total=None):
TimeSignal.__init__(self, path=path);
if(name):
self.name = name;
if(path):
self.loadFile(num_frames_total=num_frames_total);
def initializeBlank(self):
TimeSignal.initializeBlank(self);#YES KEEP
self.name = None;
self.sampling_rate = None;
self.audio=None;
self.reader = None;
self.writer = None;
self.num_frames_total=None;
self.reshape=None;
self.meta_data = None;
self.sampling_rate = None;
self.source = None;
# _gui is not saved
self._gui = None;
def _getFrameRate(self):
return self.sampling_rate;
# _gui is from TimeSignal
#
@property
def gui(self):
return self._getGui();
def _getGui(self):
return self._gui;
@gui.setter
def gui(self, value):
self._setGui(value);
def _setGui(self, value):
self._gui = value;
#
def getVersionInfo(self):
"""This is the info to be saved in asset version dictionary"""
d={};
d['name']=self.name;
d['sampling_rate']=self.sampling_rate;
d['num_frames_total']=self.num_frames_total;
d['duration']=self.getDuration();
d['start_time']=self.getStartTime();
d['end_time']=self.getEndTime();
d['meta_data']=self.meta_data;
return d;
def getName(self):
if(self.name is None):
return self.getInfo('file_name');
else:
return self.name;
def getTempDir(self):
if(self.source is not None):
return self.source.getDir('temp');
else:
return Video.VIDEO_TEMP_DIR;
def getStringForHTMLStreamingBase64(self):
svideo = io.open(self.getPath(), 'r+b').read()
encoded = base64.b64encode(svideo)
return "data:video/mp4;base64,{0}".format(encoded.decode('ascii'));
def n_frames(self):
if(not self.num_frames_total):
self.num_frames_total = self.calcNumFramesTotal();
return self.num_frames_total;
def getDuration(self):
return truediv(self.n_frames(), self.sampling_rate);
def getStartTime(self):
return 0;
def getEndTime(self):
return self.getDuration();
def getMPYClip(self, get_audio=True):
return mpy.VideoFileClip(self.getPath(), audio=get_audio);
def getAudio(self):
return self.audio;
def loadFile(self, file_path=None, num_frames_total=None):
if (file_path):
self.setPath(file_path=file_path);
if ('file_path' in self.a_info):
self.reader = imageio.get_reader(self.a_info['file_path'], 'ffmpeg');
self.meta_data = self.reader.get_meta_data();
self.sampling_rate = self.meta_data['fps'];
if (num_frames_total is not None):
self.num_frames_total = num_frames_total;
else:
self.num_frames_total = self.calcNumFramesTotal();
try:
self.audio = Audio(self.a_info['file_path']);
self.audio.name =self.name;
#except RuntimeError:
except Exception:
print(("Issue loading audio for {}".format(self.a_info['file_path'].encode('utf-8'))));
self.audio = Audio(sampling_rate=16000);
self.audio.x = np.zeros(int(np.ceil(self.audio.sampling_rate*self.getDuration())));
def openVideoWriter(self, output_file_path, fps=None):
if('outputs' not in self.a_info):
self.a_info['outputs'] = [];
out_fps = fps;
if(not out_fps):
out_fps=self.sampling_rate;
make_sure_dir_exists(output_file_path);
self.writer = imageio.get_writer(output_file_path, 'ffmpeg', macro_block_size = None, fps = out_fps);
self.a_info['outputs'].append(output_file_path);
def closeVideoWriter(self):
self.writer.close();
self.writer = None;
def getFrameShape(self):
fs=self.getInfo('frame_shape');
if(fs is not None):
return fs;
else:
self.setInfo(label='frame_shape', value=self.reader.get_data(0).shape);
return self.getInfo('frame_shape');
def calcNumFramesTotal(self):
#assert(False)
print(("Calculating frames for {}...".format(self.name)))
valid_frames = 0
example_frame = self.reader.get_data(0);
self.setInfo(label='frame_shape',value=example_frame.shape);
# https://stackoverflow.com/questions/54778001/how-to-to-tackle-overflowerror-cannot-convert-float-infinity-to-integer
#for i in range(1, self.reader.get_length()):
for i in range(1, self.reader.count_frames()):
try:
self.reader.get_data(i);
except imageio.core.format.CannotReadFrameError as e:
break
valid_frames += 1
print("Done.")
return valid_frames
def readFrameBasic(self, i):
"""You should basically never call this"""
fi=i;
if(fi<0):
fi=0;
if(fi>(self.num_frames_total-1)):
fi=(self.num_frames_total-1);
return np.asarray(self.reader.get_data(int(fi)));
def getFrame(self, f):
return self.readFrameBasic(round(f));
def getFrameFromTime(self, t):
f = t*self.sampling_rate;
return self.getFrame(f=f);
def getFrameLinearInterp(self, f):
if(isinstance(f,int) or f.is_integer()):
return self.readFrameBasic(int(f));
prev_frame = self.readFrameBasic(math.floor(f));
next_frame = self.readFrameBasic(math.ceil(f));
frame_progress = f-np.floor(f);
rframe = (next_frame*frame_progress)+(prev_frame*(1.0-frame_progress));
return rframe.astype(prev_frame.dtype);
def writeFrame(self, img):
if self.writer.closed:
print('ERROR: Vid writer object is closed.')
else:
self.writer.append_data(img.astype(np.uint8))
def play(self):
if(ISNOTEBOOK):
print("Playing video:")
video = io.open(self.getPath(), 'r+b').read()
encoded = base64.b64encode(video)
vidhtml=HTML(data=''''''.format(encoded.decode('ascii')));
IPython.display.display(vidhtml);
# return vidhtml;
else:
print("HOW TO PLAY VIDEO? NOT A NOTEBOOK.")
def show(self):
self.play();
def write(self, output_path, output_sampling_rate=None):
assert output_path, "MUST PROVIDE OUTPUT PATH FOR VIDEO"
sampling_rate = output_sampling_rate;
if(not sampling_rate):
sampling_rate=self.sampling_rate;
tempfilepath = get_temp_file_path(final_file_path=output_path, temp_dir_path=self.getTempDir());
self.openVideoWriter(output_file_path=tempfilepath, fps=output_sampling_rate);
duration = self.getDuration();
nsamples = sampling_rate*duration;
old_frame_time = truediv(1.0,self.sampling_rate);
frame_start_times = np.linspace(0,self.getDuration(),num=nsamples,endpoint=False);
frame_index_floats = frame_start_times*self.sampling_rate;
start_timer=time.time();
last_timer=start_timer;
fcounter=0;
for nf in range(len(frame_index_floats)):
self.writeFrame(self.getFrame(frame_index_floats[nf]));
fcounter+=1;
if(not (fcounter%50)):
if((time.time()-last_timer)>10):
last_timer=time.time();
print(("{}%% done after {} seconds...".format(100.0*truediv(fcounter,len(frame_index_floats)), last_timer-start_timer)));
self.closeVideoWriter();
rvid = Video.CreateFromVideoAndAudio(video_path=tempfilepath, audio_object=self.audio, output_path=output_path);
os.remove(tempfilepath);
return rvid;
def VideoClip(self, start=None, end=None, name=None):
from . import VideoClip
if(start is None):
start = 0;
if(end is None):
end = self.getDuration();
clip = VideoClip.VideoClip(video=self, start=start, end=end);
if(name):
clip.name=name;
return clip;
def getImageFromFrame(self, i):
rimage = Image(data=self.getFrame(i));
rimage.setInfo(label='parent_video', value=self.getInfo('file_path'));
rimage.setInfo(label='frame_number',value=i);
return rimage;
def getImageFromTime(self, t):
rimage = Image(data=self.getFrameFromTime(t));
rimage.setInfo(label='parent_video', value=self.getInfo('file_path'));
rimage.setInfo(label='frame_time', value=t);
return rimage;
# def getFrameShape(self):
# return self.getImageFromFrame(0).getShape();
def writeResolutionCopyFFMPEG(self, path, max_height=None):
if(max_height is None):
max_height=self.getFrameShape()[0];
mpc = self.getMPYClip();
clip_resized = mpc.resize(height=max_height); # make the height 360px ( According to moviePy documenation The width is then computed so that the width/height ratio is conserved.)
if((clip_resized.size[0]%2)>0):
clip_resized=clip_resized.crop(x1=0,width=clip_resized.size[0]-1);
# clip_resized.write_videofile(path);
MPYWriteVideoFile(clip_resized, path);
rvid = Video(path);
return rvid;
def writeFFMPEG(self, output_path):
mpc = self.getMPYClip();
# mpc.write_videofile(output_path, preset='fast', codec='mpeg4');
MPYWriteVideoFile(mpc, output_path, preset='fast', codec='mpeg4')
rvid = Video(output_path);
return rvid;
def writeResolutionCopy(self, path, max_height=None, reshape=None, input_sampling_rate_factor = None, output_sampling_rate=None):
print((self.getPath()))
if(input_sampling_rate_factor is not None):
original_sampling_rate = self.sampling_rate;
self.sampling_rate=input_sampling_rate_factor*self.sampling_rate;
original_audio_sampling_rate = self.audio.sampling_rate;
self.audio.sampling_rate=self.audio.sampling_rate*input_sampling_rate_factor;
output_path = path;
inshape = self.getFrameShape();
if(reshape==True):
imshape = [inshape[1],inshape[0],inshape[2]];
outshape = None;
if(max_height and (max_height10):
last_timer=time.time();
print(("{}%% done after {} seconds...".format(100.0*truediv(fcounter,len(frame_index_floats)), last_timer-start_timer)));
self.closeVideoWriter();
rvid = Video.CreateFromVideoAndAudio(video_path=tempfilepath, audio_object=self.audio, output_path=output_path);
os.remove(tempfilepath);
if(input_sampling_rate_factor is not None):
#return original_sampling_rate
self.sampling_rate=original_sampling_rate;
self.audio.sampling_rate = original_audio_sampling_rate;
return rvid;
def writeWarped(self, output_path, warp, output_sampling_rate=None, output_audio=None, bitrate=None, vbmark = True, max_time = None, **kwargs):
sampling_rate = output_sampling_rate;
if (not sampling_rate):
sampling_rate = self.sampling_rate;
duration = self.getDuration();
old_frame_time = truediv(1.0, self.sampling_rate);
target_start = warp.getTargetStart();
target_end = warp.getTargetEnd();
target_duration = target_end - target_start;
if(max_time is not None and target_duration>max_time):
target_duration = max_time;
target_end = target_start+max_time;
print((
"target start: {}\ntarget end: {}\ntarget duration: {}".format(target_start, target_end, target_duration)));
new_n_samples = target_duration * sampling_rate;
target_start_times = np.linspace(target_start, target_end, num=new_n_samples, endpoint=False);
unwarped_target_times = [];
for st in target_start_times:
unwarped_target_times.append(warp.warpTargetTime(st));
frame_index_floats = np.true_divide(np.array(unwarped_target_times), old_frame_time);
tempfilepath = get_temp_file_path(final_file_path=output_path, temp_dir_path=Video.VIDEO_TEMP_DIR);
self.openVideoWriter(output_file_path=tempfilepath, fps=output_sampling_rate, **kwargs);
start_timer = time.time();
last_timer = start_timer;
fcounter = 0;
if(vbmark):
vbmarker = self.getImageFromFrame(0)._vbmarker();
for nf in range(len(frame_index_floats)):
try:
nwfr = self.getFrame(frame_index_floats[nf]);
if(vbmark):
nwfrm = Image(data=nwfr);
nwfrm._splatAtPixCoord(**vbmarker);
nwfr = nwfrm._pixels_uint;
self.writeFrame(nwfr);
except ValueError:
print(("VALUE ERROR ON WRITEFRAME {}".format(frame_index_floats[nf])));
self.writeFrame(self.getFrame(math.floor(frame_index_floats[nf])));
fcounter += 1;
if (not (fcounter % 50)):
if ((time.time() - last_timer) > 10):
last_timer = time.time();
print(("{}%% done after {} seconds...".format(100.0 * truediv(fcounter, len(frame_index_floats)),
last_timer - start_timer)));
self.closeVideoWriter();
silent_warped_vid = Video(tempfilepath);
if (not output_audio):
output_audio = self.getAudio();
cropped_output_audio = output_audio.AudioClip(start=target_start, end=target_end);
if ((self.getInfo('max_height') is None) and (bitrate is None)):
use_bitrate = "20000k";
print(('Using bitrate of {}'.format(use_bitrate)));
rvid = Video.CreateFromVideoAndAudioObjects(video=silent_warped_vid, audio=cropped_output_audio,
output_path=output_path, bitrate=use_bitrate);
elif (bitrate is 'regular'):
rvid = Video.CreateFromVideoAndAudioObjects(video=silent_warped_vid, audio=cropped_output_audio,
output_path=output_path);
else:
rvid = Video.CreateFromVideoAndAudioObjects(video=silent_warped_vid, audio=cropped_output_audio,
output_path=output_path, bitrate=bitrate);
os.remove(tempfilepath);
rvid.setInfo(label='warp_used', value=warp);
return rvid;
def getVersionLabel(self):
return self.getInfo('version_label');
def getWarpsDir(self):
if(self.source is None):
return self.getTempDir();
version_label = self.getVersionLabel()
return self.source.getWarpsDir(version_label=version_label);
def getWithBeginningCroppedToAudio(self, target):
if(isinstance(target, Audio)):
B=target;
else:
B=target.getAudio();
A = self.getAudio();
AB = A.getShiftAmountTo(B);
BA = B.getShiftAmountTo(A);
if(AB n_audio_samples_sig):
nreps = math.ceil(truediv(n_audio_samples_in_vid, n_audio_samples_sig));
if (is_stereo):
audio_sig = np.concatenate(
(audio_sig, np.zeros((2, n_audio_samples_in_vid - n_audio_samples_sig))),
axis=1);
else:
audio_sig = np.tile(audio_sig, (int(nreps)));
audio_sig = audio_sig[:int(n_audio_samples_in_vid)];
if (is_stereo):
# reshapex = np.reshape(audio_sig, (audio_sig.shape[1], audio_sig.shape[0]), order='F');
reshapex = np.transpose(audio_sig);
audio_clip = MPYAudioArrayClip(reshapex, fps=audio_sampling_rate); # from a numeric arra
else:
reshapex = audio_sig.reshape(len(audio_sig), 1);
reshapex = np.concatenate((reshapex, reshapex), axis=1);
audio_clip = MPYAudioArrayClip(reshapex, fps=audio_sampling_rate); # from a numeric arra
video_clip = video_object.getMPYClip();
video_clip = video_clip.set_audio(audio_clip);
# video_clip.write_videofile(output_path,codec='libx264', write_logfile=False);
if (bitrate is None):
# video_clip.write_videofile(output_path, codec=codec, write_logfile=False);
MPYWriteVideoFile(video_clip, output_path, codec=codec, write_logfile=False);
else:
MPYWriteVideoFile(video_clip, output_path, codec=codec, write_logfile=False, bitrate=bitrate);
# video_clip.write_videofile(output_path, codec=codec, write_logfile=False, bitrate=bitrate);
if (return_vid):
return Video(output_path);
else:
return True;
@staticmethod
def CreateByStackingVideos(video_objects=None, video_paths=None, output_path=None, audio = None, concatdim = 0, force_recompute=True, **kwargs):
assert output_path, "MUST PROVIDE OUTPUT PATH FOR VIDEO"
if(not force_recompute):
if(os.path.isfile(output_path)):
return Video(path=output_path);
matchdim = (concatdim+1)%2;
vids=[];
if(video_objects is not None):
vids=video_objects;
if(video_paths is not None):
for vp in video_paths:
vids.append(Video(path=video_paths));
output_path=output_path.encode(sys.getfilesystemencoding()).strip();
make_sure_dir_exists(output_path);
basevid = vids[0];
if(audio is None):
audio = basevid.audio;
sampling_rate = basevid.sampling_rate;
tempfilepath = get_temp_file_path(final_file_path=output_path, temp_dir_path=vids[0].getTempDir());
basevid.openVideoWriter(output_file_path=tempfilepath, fps=sampling_rate);
duration = basevid.getDuration();
nsamples = sampling_rate*duration;
old_frame_time = truediv(1.0,sampling_rate);
#frame_start_times = np.linspace(self.getStartTime(),self.getEndTime(),num=nsamples,endpoint=False);
frame_start_times = np.linspace(0,duration,num=nsamples,endpoint=False);
#frame_index_floats = frame_start_times/old_frame_time;
frame_index_floats = frame_start_times*sampling_rate;
for nf in range(len(frame_index_floats)):
frameind = frame_index_floats[nf];
newframe = basevid.getFrame(frameind);
for vn in range(1,len(vids)):
addpart = vids[vn].getFrame(frameind);
partsize = np.asarray(addpart.shape)[:];
cumulsize = np.asarray(newframe.shape)[:];
if(partsize[matchdim]!=cumulsize[matchdim]):
sz = partsize[:];
sz[matchdim]=cumulsize[matchdim];
addpart = sp.misc.imresize(addpart, size=sz);
newframe = np.concatenate((newframe, addpart), concatdim);
basevid.writeFrame(newframe);
basevid.closeVideoWriter();
rvid = Video.CreateFromVideoAndAudio(video_path=tempfilepath, audio_object=audio, output_path=output_path, **kwargs);
os.remove(tempfilepath);
return rvid;
@staticmethod
def CreateFromVideoAndAudioPaths(video_path, audio_path, output_path, return_vid = True, **kwargs):
return Video.CreateFromVideoAndAudio(video_path=video_path, audio_path=audio_path, output_path=output_path,return_vid=return_vid, **kwargs);
@staticmethod
def CreateFromVideoAndAudioObjects(video, audio, output_path, clip_to_video_length=True, return_vid = True, **kwargs):
return Video.CreateFromVideoAndAudio(video_object=video, audio_object=audio, output_path=output_path, clip_to_video_length=clip_to_video_length, return_vid = return_vid, **kwargs);
def _getDefaultPeakPickingTimeParams(self, **kwargs):
single_frame = np.true_divide(1.0, self._getFrameRate());
time_params = dict(
pre_max_time=2.0 * single_frame,
post_max_time=2.0 * single_frame,
pre_avg_time=5.0 * single_frame,
post_avg_time=5.0 * single_frame,
wait_time=2.0 * single_frame,
delta=0.015,
)
time_params.update(kwargs);
return time_params;
# ###################
# FEATURE
def getFrameIndexes(self, force_recompute=False):
feature_name = 'frame_indexes';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = dict();
duration = self.getDuration();
nsamples = self.sampling_rate * duration;
frame_start_times = np.linspace(0, duration, num=nsamples, endpoint=False);
value = frame_start_times * self.sampling_rate;
self.setFeature(name=feature_name, value=value, params=params);
return self.getFeature(feature_name);
def getFeaturesList(self):
return super(Video, self).getFeaturesList()+self.audio.getFeaturesList();
def getVideoFeaturesList(self):
return super(Video, self).getFeaturesList();
def getFeatureFunctionsList(self):
return super(Video, self).getFeatureFunctionsList()+self.audio.getFeatureFunctionsList();
def getFeatureSourceType(self, name):
"""returns whether video or audio feature, instead of parent version which returns true or false"""
vidhas = super(Video, self).hasFeature(name=name);
if(vidhas):
return 'video';
audiohas = self.audio.hasFeature(name=name);
if(audiohas):
return 'audio';
return None;
def getFeature(self, name, force_recompute=False, **kwargs):
"""Returns None if feature is not already computed, and feature name is not implemented and registered with FEATURE_FUNCS"""
params = kwargs;
assert(not kwargs.get('params')), "STILL TRYING TO USE PARAMS INSTEAD OF KWARGS. FIX THIS";
ftry = super(Video, self).getFeature(name=name, force_recompute=force_recompute, **kwargs);
if(ftry is not None):
return ftry;
else:
return self.audio.getFeature(name=name, force_recompute=force_recompute, **kwargs);
Video.FEATURE_FUNCS['frame_indexes']=Video.getFrameIndexes;
from . import Video_CV;
if(Video_CV.USING_OPENCV):
Video.FEATURE_FUNCS.update(Video_CV.FEATURE_FUNCS);
Video.USING_OPENCV = Video_CV.USING_OPENCV;
Video.localRhythmicSaliencyFunction = Video_CV.localRhythmicSaliencyFunction
Video.visualBeatFunction = Video_CV.visualBeatFunction
Video.cvGetGrayFrame = Video_CV.cvGetGrayFrame;
Video.getImageFromFrameGray = Video_CV.getImageFromFrameGray;
Video.plotVisualBeats = Video_CV.plotVisualBeats;
Video.loadFlowFeatures = Video_CV.loadFlowFeatures;
Video.getVisualBeats = Video_CV.getVisualBeats
Video.getLocalRhythmicSaliency = Video_CV.getLocalRhythmicSaliency;
Video.getDirectogram = Video_CV.getDirectogram;
Video.getDirectogramPowers = Video_CV.getDirectogramPowers;
Video.getVisibleImpactEnvelope = Video_CV.getVisibleImpactEnvelope;
Video.getVisibleImpactEnvelopePowers = Video_CV.getVisibleImpactEnvelopePowers;
Video.getVisibleImpacts = Video_CV.getVisibleImpacts;
Video.getVisualBeats = Video_CV.getVisualBeats;
# Video.getBackwardVisualBeats = Video_CV.getBackwardVisualBeats;
# Video.getForwardVisualBeats = Video_CV.getForwardVisualBeats;
Video.getBackwardVisibleImpactEnvelope = Video_CV.getBackwardVisibleImpactEnvelope;
Video.getBothWayVisibleImpactEnvelope = Video_CV.getBothWayVisibleImpactEnvelope;
Video.getForwardVisibleImpactEnvelope = Video_CV.getForwardVisibleImpactEnvelope;
Video.getDirectionalFlux = Video_CV.getDirectionalFlux;
Video.getVisualTempogram = Video_CV.getVisualTempogram;
Video.getCutEvents = Video_CV.getCutEvents;
Video.computeImpactEnvelope = Video_CV.computeImpactEnvelope;
Video.computeDirectogramPowers = Video_CV.computeDirectogramPowers;
Video.visualBeatsFromEvents = Video_CV.visualBeatsFromEvents;
Video.plotVisualBeats = Video_CV.plotVisualBeats;
Video.plotImpactEnvelope = Video_CV.plotImpactEnvelope;
Video.plotVisibleImpacts = Video_CV.plotVisibleImpacts;
Video.getVisualBeatSequences = Video_CV.getVisualBeatSequences;
Video.printVisualBeatSequences = Video_CV.printVisualBeatSequences;
Video.getVisualBeatTimes = Video_CV.getVisualBeatTimes;
Video.findAccidentalDanceSequences = Video_CV.findAccidentalDanceSequences;
Video.plotEvents = Video_CV.plotEvents;
# Video. = Video_CV.
# Video. = Video_CV.
# Video. = Video_CV.
# Video. = Video_CV.
# Video. = Video_CV.
# Video. = Video_CV.
else:
AWARN("Was not able to add functions that use OpenCV! Check OpenCV instalation and try again?");
from .vbgui import BeatGUI
if(BeatGUI.VIEWER_INSTALLED):
def getEvents(self, **kwargs):
time_params = self._getDefaultPeakPickingTimeParams();
time_params.update(kwargs)
vbeats = self.getFeature('visual_beats', force_recompute=True, **time_params);
return vbeats;
def getEventList(self, **kwargs):
events = self.getEvents(**kwargs);
return EventList(events=events);
def runBeatGUIOnAudio(self):
audio = self.getAudio();
self.gui.run(local_saliency=audio.getLocalRhythmicSaliency(), frame_rate = audio._getFrameRate(), eventlist = audio.getEventList());
def runGUI(self, local_saliency=None, frame_rate = None, eventlist = 'default', frame_offset=None):
self.gui.run(local_saliency=local_saliency, frame_rate=frame_rate, eventlist=eventlist, frame_offset=frame_offset);
Video._getGui = BeatGUI.media_GUI_func;
Video.runGUI = runGUI;
Video.getEvents = getEvents;
Video.getEventList = getEventList;
Video.runBeatGUIOnAudio = runBeatGUIOnAudio;
else:
AWARN("BeatGUI not installed");
================================================
FILE: src/video2npz/visbeat3/visbeat3/VideoClip.py
================================================
from .Video import *
from .AudioClip import *
class VideoClip(Video):
"""VideoClip (class): A segment of a video, and a bunch of convenience functions to go with it.
Attributes:
start: The name of the video
end: The framerate of the video
"""
def AOBJECT_TYPE(self):
return 'VideoClip';
def __init__(self, video=None, start=None, end=None, clip_to_frame=True, path=None):
"""If a video is provided, we don't want to reload the video from disk. If a path is provided, we have no choice.
"""
assert(not (video and path)), "provided both video object and path to VideoClip constructor."
assert((start is not None) and (end is not None)), "must provide start time and end time to AudioClip constructor"
Video.__init__(self, path = path);
self.initializeBlank();
self.start = start;
self.end = end;
if(video):
self.setPath(video.getPath());
self.reader = video.reader;
#self.writer = None; #this only comes up if we write later
self.sampling_rate=video.sampling_rate;
self.num_frames_total=video.num_frames_total;
time_per_frame=truediv(1.0,self.sampling_rate);
if(clip_to_frame):
self.start=time_per_frame*math.floor(truediv(self.start,time_per_frame));
self.end=time_per_frame*math.floor(truediv(self.end,time_per_frame));
if(video.name):
self.name = video.name+"_{}_{}".format(start,end);
self.audio = video.audio.AudioClip(start=start, end=end);
else:
assert(False),"must provide video to VideoClip init"
def initializeBlank(self):
Video.initializeBlank(self);
self.start = None;
self.end = None;
# def readFrameBasic(self, i):
# return Video.getFrame(self, float(i)+self.start);
def getFrameLinearInterp(self, f):
return Video.getFrameLinearInterp(self, float(f)+self.start*self.sampling_rate);
def getFrame(self, f):
return Video.getFrame(self, float(f)+self.start*self.sampling_rate);
def getDuration(self, round_to_frames=False):
if(not round_to_frames):
return self.end-self.start;
else:
return truediv(self.n_frames(), self.sampling_rate);
def n_frames(self):
#return self.getLastFrameIndex()-self.getFirstFrameIndex();
return math.ceil((self.end-self.start)*self.sampling_rate);
# def getFirstFrameIndex(self):
# return math.floor(self.start*self.sampling_rate);
#
# def getLastFrameIndex(self):
# #I think floor is still right here, because the times mark beginnings of frames
# return math.floor(self.end*self.sampling_rate);
def getStartTime(self):
return self.start;
def getEndTime(self):
return self.end;
def getMPYClip(self, get_audio=True):
return mpy.VideoFileClip(self.getPath(), audio=get_audio).subclip(self.getStartTime(), self.getEndTime());
def play(self):
if(ISNOTEBOOK):
print("Playing video:")
IPython.display.display(self.getMPYClip().ipython_display(fps=self.sampling_rate, maxduration=self.getDuration()+1));
else:
print("HOW TO PLAY VIDEO? NOT A NOTEBOOK.")
================================================
FILE: src/video2npz/visbeat3/visbeat3/VideoSource.py
================================================
from .VisBeatImports import *
from .Video import *
from .AFileManager import AFileManager
try:
import youtube_dl
except ImportError:
AWARN('You need to install youtube-dl to use parts of VideoSource class that pull from YouTube. Try running:\npip install youtube-dl')
def safe_file_name(input_string):
return ''.join([i if ord(i) < 128 else '_' for i in input_string]);
class VideoSource(AFileManager):
"""Video (class): A video, and a bunch of convenience functions to go with it.
Attributes:
name: The name of the video
sampling_rate: The framerate of the video
audio: an Audio object, the audio for the video
"""
VIDEO_TEMP_DIR = './'
def getJSONName(self):
return self.AOBJECT_TYPE()+".json";
def AOBJECT_TYPE(self):
return 'VideoSource';
def __init__(self, path, name=None, source_location=None, VideoClass = None, **kwargs):
"""
:param path: either the path to a json, or the path to a directory containing 'VideoSource.json',
or the path to a directory where said json should be created.
:param name: name for video
:param source_location: can be a path to a video file, or a youtube source from which to pull a video file
:param VideoClass: visbeat.Video by default, but can be changed if you are using a custom subclass.
Must be a subclass of visbeat.Video, and must be constructable with VideoClass(path)
"""
AFileManager.__init__(self, path=path);
if(VideoClass is not None):
self.VideoClass = VideoClass;
self.setSource(source_location=source_location, assert_valid=None, **kwargs);
# if (self.name is None):
# self.name = os.path.splitext(os.path.basename(path))[0]
@staticmethod
def NewVideoSource(destination, name, source_location=None, VideoClass = None, **kwargs):
vsdir = os.path.join(destination, name+os.sep);
make_sure_dir_exists(vsdir);
print(("Video source at {}".format(vsdir)));
return VideoSource(path=vsdir, name=name, source_location=source_location, **kwargs);
def initializeBlank(self):
AFileManager.initializeBlank(self);
self.source_location = None;
self.name = None;
self.video_file_name = None;
self.title_safe = None;
self.youtube_info_dict = None;
self.versions_info = {};
#
self.VideoClass = Video;
def toDictionary(self):
d = AFileManager.toDictionary(self);
d['source_location']=self.source_location;
if(self.name):
d['name']=self.name;
if(self.video_file_name):
d['video_file_name']=self.video_file_name;
if(self.title_safe):
d['title_safe']=self.title_safe;
if(self.youtube_info_dict):
d['youtube_info_dict']=self.youtube_info_dict;
if(self.versions_info):
d['versions_info']=self.versions_info;
return d;
def initFromDictionary(self, d):
AFileManager.initFromDictionary(self, d);
self.source_location = d['source_location'];
self.name = d.get('name');
self.video_file_name = d.get('video_file_name');
self.title_safe = d.get('title_safe');
self.youtube_info_dict = d.get('youtube_info_dict');
self.versions_info=d.get('versions_info');
if(self.versions_info is None):
self.versions_info = {};
#do class specific inits with d;
def initWithPath(self, path=None, clear_temp=None):
AFileManager.initWithPath(self, path=path, clear_temp=clear_temp);
self.setDir('versions', pathstring(self.getDirectoryPath() + os.sep + "Versions" + os.sep));
self.setDir('warps', pathstring(self.getDir('versions')+ os.sep + "Warps" + os.sep));
# self.setDir('midi', pathstring(self.getDirectoryPath() + os.sep + "MIDI" + os.sep));
# self.setDir('music', pathstring(self.getDirectoryPath() + os.sep + "Music" + os.sep));
self.setFeaturesDir();
def setFeaturesDir(self, features_dir=None):
if (features_dir is None):
self.setDir('features', pathstring(self.getDir('data') + os.sep + "Features" + os.sep))
else:
self.setDir('features', features_dir);
def getName(self):
"""
Gets name if set. If not set, returns file name without extension.
:return:
"""
if(self.name is not None):
return self.name;
elif(self.video_file_name is not None):
return os.path.splitext(self.video_file_name)[0];
else:
return None;
###################
@staticmethod
def _versionLabelString(version_label=None):
if (version_label and version_label != 'Full'):
return str(version_label);
else:
return 'Full';
@staticmethod
def _versionGroupString(version_group=None):
if (version_group is None):
version_group = 'Original';
return version_group;
@staticmethod
def _getVersionLabelDirName(version_label=None):
if(isinstance(version_label, int)):
return ("maxheight_{}".format(version_label));
else:
return "Full";
def getVersionPath(self, version_label=None, version_group=None):
"""
Get path to version of video (path to video file). Return None if version has not been added.
:param version_label:
:return:
"""
return self.getVersionInfo(version_label=version_label, version_group=version_group, info_label='path');
def getDirForVersion(self, version_label=None, version_group=None):
vdir = self.getDir('versions') + os.sep + self._versionGroupString(version_group) + os.sep + self._getVersionLabelDirName(version_label)+os.sep;
return vdir;
def getVersionInfo(self, version_label, version_group=None, info_label=None):
"""
Get info about a version of the video
:param version_label:
:param info_label:
:return:
"""
assert(info_label is not None), "should provide info_label to getVersionInfo()"
d = self.getVersionDictionary(version_label=version_label, version_group=version_group);
if(d is not None):
return d.get(info_label);
else:
return None;
def getVersionDictionary(self, version_label=None, version_group=None):
if(version_group is None):
version_group='Original';
vis_d=self.versions_info.get(version_group);
if(vis_d is not None):
return vis_d.get(VideoSource._versionLabelString(version_label));
else:
return None;
def setVersionDictionary(self, version_label=None, version_group=None, d=None):
if(version_group is None):
version_group='Original';
vis_d=self.versions_info.get(version_group);
if(vis_d is None):
self.versions_info[version_group]={};
vis_d=self.versions_info.get(version_group);
vis_d[VideoSource._versionLabelString(version_label)]=d;
return;
def setVersionInfo(self, version_label=None, version_group=None, video_path=None, **kwargs):
version_dict = self.getVersionDictionary(version_label=version_label, version_group=version_group);
if(version_dict is None):
self.setVersionDictionary(version_label=version_label, version_group=version_group, d={});
version_dict = self.getVersionDictionary(version_label=version_label, version_group=version_group);
if(video_path is not None):
version_dict.update({'path':str(pathstring(video_path))});
if(kwargs is not None):
version_dict.update(kwargs);
####################
def hardSave(self):
if (os.path.isfile(self.getJSONPath())):
os.rename(self.getJSONPath(), self.getDir('backup') + os.sep + self.AOBJECT_TYPE() + ".json");
self.writeToJSON(self.getJSONPath());
def save(self):
if (self.getInfo('block_writing_to_json')):
return;
self.hardSave();
####################
# def removeAllVersionFiles(self, asset_manager=None):
# AWARN("This should wipe the directory, ya?")
# # AWARN("Remove all version files does not remove features and vis images! This still needs to be implemented!")
# # for vtype in self.versions_info:
# # for v in self.versions_info.get(vtype):
# # # print(self.versions_info.get(vtype).get(v));
# # vpath = self.versions_info.get(vtype).get(v).get('path');
# # assert(vpath), "version {} did not have path".format(vtype)
# # print(vpath)
# # if(os.path.isfile(vpath)):
# # print("REMOVING {}".format(vpath))
# # os.remove(vpath);
# # if(asset_manager is not None and vtype=='Original'):
# # if(v=='Full'):
# # rs=None;
# # else:
# # rs = int(v);
# # asset_manager.removeFeaturesForLinkRes(link=self, max_height=rs);
# # return True;
# def removeFeaturesForRes(self, max_height=None):
# v = self.getVersionVideo(name=link.name, max_height = max_height);
# v.clearFeatureFiles(features_to_clear=['all', 'each']);
#
#
# def removeFeatureFilesForVideo(self, video, features_to_remove=None):
# if(features_to_remove is None):
# return;
# if(not isinstance(features_to_remove, list)):
# features_to_remove=[features_to_remove];
# for f in features_to_remove:
# self.removeFeatureFileForVideo(video=video, feature_name=f);
#
#
# def removeFeatureFileForVideo(self, video, feature_name):
# AWARN("still need to implement removeFeatureFileForVideo. Should just empty corresponding directory. Also implement 'each' that removes all.")
# # if(feature_name=='each'):
# # return self.removeFeatureFilesForVideo(video=video, features_to_remove=video.getFeatureFunctionsList());
# # max_height = video.getInfo(label='max_height');
# # link = self.hasLinkWithName(name=video.name);
# # source_type=video.getFeatureSohahurceType(feature_name);
# # ipath = self.getFeaturePathForLink(feature_name=feature_name, link=link, max_height=max_height, source_type=source_type);
# # if(os.path.isfile(ipath)):
# # print("REMOVING {}".format(ipath));
# # os.remove(ipath);
#
# def removeFeatureFiles(self, video, feature_name):
# if(feature_name=='each'):
# AWARN("IMPLEMENT DELETE FEATURE DIR AND CREATE CLEAN");
# version_label = video.getInfo(label='version_label');
# AWARN("IMPLEMENT DELETE {} FOR VERSION_LABEL {}".format(feature_name, version_label));
# # ipath = self.getFeaturePathForLink(feature_name=feature_name, link=link, max_height=max_height, source_type=source_type);
# # if(os.path.isfile(ipath)):
# # print("REMOVING {}".format(ipath));
# # os.remove(ipath);
#
# def removeVersion(self, version_label=None, remove_files=True):
# AWARN("Remove Resolution does not remove features! This still needs to be implemented!")
# for vtype in self.versions_info:
# v = self.versions_info.get(vtype).get(VideoSource._versionLabelString(version_label));
# if(v is not None):
# vpath = v.get('path');
# if(os.path.isfile(vpath)):
# print("REMOVING {}".format(vpath))
# os.remove(vpath);
# self.versions_info.get(vtype).pop(VideoSource._versionLabelString(version_label), None);
# return True;
#
# def copyResolutionTo(self, version_label=None, output_dir=None):
# assert(output_dir)
# for vtype in self.versions_info:
# v = self.versions_info.get(vtype).get(VideoSource._versionLabelString(version_label));
# if(v is not None):
# vpath = v.get('path');
# if(os.path.isfile(vpath)):
# opath = os.path.join(output_dir,(vtype+'_'+VideoSource._versionLabelString(version_label)+self.video_file_name));
# print("COPYING {} to {}".format(vpath,opath));
# shutil.copy2(vpath, opath);
# return True;
#
# def copyAssetsTo(self, output_dir=None, asset_manager=None):
# for vtype in self.versions_info:
# output_type_dir=pathstring(output_dir+os.sep+vtype+os.sep);
# make_sure_dir_exists(output_type_dir);
# for v in self.versions_info.get(vtype):
# output_a_dir = pathstring(output_type_dir+os.sep+v+os.sep);
# make_sure_dir_exists(output_a_dir);
# # print(self.versions_info.get(vtype).get(v));
# vpath = self.versions_info.get(vtype).get(v).get('path');
# if(vpath and os.path.isfile(vpath)):
# print("copying {} to {}".format(vpath, output_a_dir));
# shutil.copy2(vpath, output_a_dir);
# if(asset_manager is not None and vtype=='Original'):
# if(v=='Full'):
# rs=None;
# else:
# rs = int(v);
# asset_manager.saveFeaturesForVersion(version_label=rs, output_dir = output_a_dir);
def getWarpsDir(self, version_label=None):
warpdir = self.getDir('warps');
resdir = self._getVersionLabelDirName(version_label=version_label);
rdir = pathstring(warpdir + os.sep + resdir + os.sep);
make_sure_path_exists(rdir);
return rdir;
# ############################# FROM ASSETMANAGER #######################
def getVersion(self, max_height=None, get_if_missing=True, load_features=True, **kwargs):
"""
Gets a version of the video with maximum height max_height. This function contains logic to decide whether/when
to pull the video. Use pullVersion to force pulling that overwrite's existing assets.
:param max_height:
:param get_if_missing:
:return:
"""
vpath = self.getVersionPath(version_label=max_height);
if(vpath and os.path.isfile(vpath)):
num_frames_total = self.getVersionInfo(version_label=max_height, info_label='num_frames_total');
if(num_frames_total):
v = self.RegisteredVideo(path=vpath, version_label = max_height, num_frames_total=num_frames_total, load_features=True);
else:
v = self.RegisteredVideo(path=vpath, version_label = max_height, load_features=True);
self.setVersionInfo(version_label=max_height, num_frames_total=v.num_frames_total);
self.save();
return v;
else:
if(get_if_missing):
vpath = self.pullVersion(max_height=max_height, **kwargs);
if(vpath):
num_frames_total = self.getVersionInfo(version_label=max_height, info_label='num_frames_total');
if(num_frames_total):
v = self.RegisteredVideo(path=vpath, version_label = max_height, num_frames_total=num_frames_total, load_features=True);
else:
v = self.RegisteredVideo(path=vpath, version_label=max_height, load_features=True);
self.setVersionInfo(version_label=max_height, num_frames_total=v.num_frames_total);
self.save();
else:
AWARN("COULDNT GET VIDEO FROM {}".format(self.source_location));
else:
AWARN("COULDNT FIND VIDEO LOCALLY");
return;
return v;
def saveFeaturesForVideo(self, video, features_to_save=None, output_dir=None, overwrite=True):
if(features_to_save is None):
return;
if(not isinstance(features_to_save, list)):
features_to_save=[features_to_save];
for f in features_to_save:
self.saveFeatureForVideo(video=video, feature_name=f, output_dir=output_dir, overwrite=overwrite);
def saveFeatureForVideo(self, video, feature_name, output_dir=None, overwrite=True):
if(feature_name=='each'):
return self.saveFeaturesForVideo(video=video, features_to_save=video.getFeaturesList(), output_dir=output_dir, overwrite=overwrite);
version_label = video.getInfo(label='version_label');
source_type = video.getFeatureSourceType(feature_name);
opath = self.getFeaturePath(feature_name=feature_name, version_label=version_label, source_type=source_type, output_dir=output_dir);
make_sure_dir_exists(opath);
if(not os.path.isfile(opath) or overwrite):
if(feature_name=='all'):
video.saveFeatures(path=opath);
return;
else:
vfeature = video.getFeature(name=feature_name, force_recompute=False);
if(vfeature is not None):
video.saveFeature(name=feature_name, path=opath);
def loadFeaturesForVideo(self, video, features_to_load=None):
if(features_to_load is None):
return;
if(not isinstance(features_to_load, list)):
features_to_load=[features_to_load];
for f in features_to_load:
self.loadFeatureForVideo(video=video, feature_name=f);
def loadFeatureForVideo(self, video, feature_name):
if(feature_name=='each'):
return self.loadFeaturesForVideo(video=video, features_to_load=video.getFeatureFunctionsList());
version_label = video.getInfo(label='version_label');
source_type=video.getFeatureSourceType(feature_name);
ipath = self.getFeaturePath(feature_name=feature_name, version_label=version_label, source_type=source_type);
if(os.path.isfile(ipath)):
if(feature_name=='all'):
video.loadFeatures(path=ipath);
else:
video.loadFeature(name=feature_name, path=ipath);
def getFeaturePath(self, feature_name=None, source_type=None, version_label=None, output_dir=None):
assert(feature_name is not None), 'must provide name of feature VideoSource.getFeaturePath'
feature_dir = self.getFeatureDir(feature_name=feature_name, source_type = source_type);
fileext = '.pkl';
if(output_dir is None):
version = self._getVersionLabelDirName(version_label=version_label)+os.sep;
output_dir = pathstring(feature_dir);
outname = self.getName();
if(outname is None):
outname = 'version';
outname = outname+'_'+self._getVersionLabelDirName(version_label=version_label)+fileext;
opath = os.path.join(output_dir, outname);
return opath;
def getFeatureDir(self, feature_name=None, source_type=None):
if(source_type is None):
source_type='video'; # could be 'audio'
# AWARN("getDir('features')= {}\nsource_type= {}\nfeature_name= {}".format(self.getDir('features'), source_type, feature_name))
ftypedir = pathstring(self.getDir('features') + os.sep + source_type + os.sep + feature_name + os.sep);
return ftypedir;
def saveFeaturesForVersion(self, version_label=None, output_dir=None):
assert(output_dir), 'must provide output dir';
v = self.getVersion(max_height=version_label);
v.save(features_to_save='all', output_dir=output_dir);
def RegisteredVideo(self, path=None, version_label=None, version_group = None, num_frames_total=None, load_features = True):
v = self.VideoClass(path=path, name=self.getName()+'_'+self._versionLabelString(version_label=version_label), num_frames_total=num_frames_total);
# v = Video(path=path, name=self.getName()+'_'+self._versionLabelString(version_label=version_label), num_frames_total=num_frames_total);
self.RegisterVideo(video=v, version_label=version_label, load_features=load_features);
return v;
def RegisterVideo(self, video, version_label = None, version_group = None, load_features=True):
def videosave(vidob, features_to_save='all', output_dir=None, overwrite=True):
self.saveFeaturesForVideo(video=vidob, features_to_save=features_to_save, output_dir=output_dir, overwrite=overwrite);
#self.save
def videoload(vidob, features_to_load='all', input_dir=None):
self.loadFeaturesForVideo(video=vidob, features_to_load=features_to_load);
def videoclear(vidob, features_to_clear='all'):
self.removeFeatureFilesForVideo(video=vidob, features_to_remove=features_to_clear);
video.setInfo(label='version_label', value=version_label);
video.setInfo(label='version_group', value=version_group);
video.setInfo(label='video_file_name', value=os.path.split(video.getPath())[1]);
# if(version_group is None):
video.save_func = videosave;
video.load_func = videoload;
video.clear_feature_files_func = videoclear;
video.source=self;
if(load_features is True and hasattr(video, "loadFlowFeatures")):
video.loadFlowFeatures();
elif(load_features is not None and (isinstance(load_features, list) or isinstance(load_features, str))):
video.load(features_to_load = load_features);
# return video;
def addVersion(self, path, version_label=None, version_group=None):
v = self.RegisteredVideo(path=path, version_label=version_label);
video_dict=v.getVersionInfo();
video_dict.update(dict(version_group=version_group));
self.setVersionInfo(video_path = path, version_label=version_label, **video_dict);
self.save();
def addVersionToVideo(self, video, new_video, version_label=None, version_group=None):
version_label = video.getInfo(label='version_label');
video_dict = new_video.getVersionInfo();
if ((version_group is not None) or (video_dict.get('version_group') is None)):
video_dict.update(dict(version_group=version_group));
self.setVersionInfo(video_path=new_video.getPath(), version_label=version_label, **video_dict);
self.save();
def setSource(self, source_location=None, assert_valid=True, **kwargs):
"""
Sets the source of this VideoSource. If file, copies the file to VideoSource directory as "Original" version,
unless copy argument is set to false.
:param source_location: either path to file, or youtube url
:param kwargs: see setSourceYoutube or setSourceFile for options
:return:
"""
if(source_location):
if(os.path.isfile(source_location)):
self.setSourceFile(path = source_location, **kwargs);
else:
self.setSourceYoutube(url=source_location, **kwargs);
return;
elif(kwargs.get('video_path')):
self.setSourceFile(**kwargs);
return;
elif(kwargs.get('url')):
self.setSourceYoutube(**kwargs);
return;
else:
if(assert_valid):
assert(False),'No valid source location provided to setSource.'
def setSourceYoutube(self, url=None, max_height=None, pull_fullres=True, **kwargs):
self.source_location=url;
self.setInfo(label='source_type', value='youtube');
if(pull_fullres):
self.pullYoutubeVideo(max_height=max_height, **kwargs);
self.save();
def setSourceFile(self, path=None, copy=True, **kwargs):
# assert(os.path.isfile(path)), 'Tried to set source but no file exists at {}'.format(path);
if(not os.path.isfile(path)):
return None;
self.video_file_name = os.path.basename(path);
if(not copy):
self.source_location = path;
self.setInfo(label='source_type', value='file_address');
return path;
# output_dir = self.getDir('versions') + os.sep + 'Original' + os.sep;
output_dir = self.getDirForVersion(version_label=None, version_group='Source');
make_sure_dir_exists(output_dir);
output_path = os.path.join(output_dir, self.video_file_name);
# max_height = kwargs.get('max_height');
# if(max_height is not None):
# # print('max_height was {}'.format(max_height));
# original = self.VideoClass(path=path);
# original.writeResolutionCopyFFMPEG(path=output_path, max_height=kwargs.get('max_height'));
# else:
# shutil.copy2(path, output_path);
shutil.copy2(path, output_path);
# self.addVersion(path=output_path, version_label='Original');
self.addVersion(path=output_path, version_label='Full');
self.setInfo(label='source_type', value='file');
self.source_location = output_path;
self.save();
return output_path;
def pullVersion(self, max_height=None, **kwargs):
# assert(self.source_location is not None), "Could not pull version; source location is None."
if(self.source_location is None):
return None;
source_type = self.getInfo('source_type');
if(source_type=='youtube'):
return self.pullYoutubeVideo(max_height=max_height, **kwargs);
else:
return self.pullFileVideo(max_height=max_height, **kwargs)
def pullFileVideo(self, max_height=None, force_recompute=None):
original_path = self.source_location;
assert(os.path.isfile(original_path)), 'SOURCE FILE {} IS MISSING'.format(self.source_location);
original = self.VideoClass(path=original_path);
output_dir = self.getDirForVersion(version_label=max_height, version_group=None);
make_sure_dir_exists(output_dir);
output_path = os.path.join(output_dir, self.video_file_name);
if(max_height is None):
if(os.path.normpath(original_path) != os.path.normpath(output_path)):
shutil.copy2(original_path, output_path);
else:
original.writeResolutionCopyFFMPEG(path=output_path, max_height=max_height);
self.addVersion(path=output_path, version_label=max_height);
return self.getVersionPath(version_label=max_height);
def pullYoutubeVideo(self, max_height=None, write_subtitles=False, save_youtube_info=False,
force_redownload=False):
"""
Downloads video from youtube with height<=max_height. Returns path to downloaded video.
:param max_height: maximum height of video to download
:param write_subtitles: whether to save the subtitles
:param save_youtube_info: whether to save the info json
:param force_redownload: whether to re-download if video exists
:return:
"""
assert (not self.getInfo('source_is_file')), "tried to call pullYoutubeVideo on file source {}.".format(self.getName());
old_vid_path = self.getVersionPath(version_label=max_height);
if ((not force_redownload) and old_vid_path and os.path.isfile(old_vid_path)):
AWARN("Old video version exists with path {}\nSkipping download...\n".format(old_vid_path))
return old_vid_path;
# output_dir = self.getDir('versions') + os.sep + self._getVersionLabelDirName(version_label=max_height) + os.sep;
output_dir = self.getDirForVersion(version_label=max_height, version_group=None);
make_sure_path_exists(output_dir);
if ((not force_redownload) and self.video_file_name is not None):
path_guess = os.path.join(output_dir, self.video_file_name);
if (os.path.isfile(path_guess)):
AWARN("found existing file {}\nSkipping download; set force_redownload=True to overwrite old version.".format(path_guess));
self.addVersion(path=path_guess, version_label=max_height);
return path_guess;
########Download From YouTube#########
vidpath_template = output_dir + '%(title)s-%(id)s' + '.%(ext)s';
ydl_opts = {
'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
'outtmpl': vidpath_template,
}
if (write_subtitles):
ydl_opts['writesubtitles'] = True;
ydl_opts['subtitlesformat'] = '[srt]';
if (max_height):
ydl_opts['format'] = 'bestvideo[height<={}][ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best'.format(
max_height);
ydl_opts['writeinfojson'] = True;
info_dict = None;
AWARN("Downloading {} from {}...".format(self.getName(), self.source_location));
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
info_dict = ydl.extract_info(self.source_location, download=True)
# video_source = info_dict.get("source", None)
# video_id = info_dict.get("id", None)
# video_title = info_dict.get('title', None)
usedtitle = info_dict['title'].replace('"', "'").replace('|', '_').replace(':', ' -').replace('/','_').replace('?', '');
usedfilename_withoutext = usedtitle + '-' + info_dict['id'];
usedfilename = usedfilename_withoutext + '.' + info_dict['ext'];
filepath = output_dir + os.sep + usedfilename;
filepathsafe = safe_file_name(filepath);
if (os.path.isfile(filepath)):
os.rename(filepath, filepathsafe);
else:
fpath = glob.glob(output_dir + os.sep + '*' + info_dict['id'] + '.mp4');
assert (len(fpath) == 1), "Wrong number of files for {}\nFound:\n{}".format(filepath, fpath);
os.rename(fpath[0], filepathsafe);
jpath = glob.glob(output_dir + os.sep + '*' + info_dict['id'] + '.info.json');
os.rename(jpath[0], safe_file_name(usedfilename_withoutext + '.info.json'));
print(("Saved to {}".format(filepathsafe)));
self.video_file_name = safe_file_name(usedfilename);
self.title_safe = safe_file_name(usedtitle);
if (save_youtube_info):
self.youtube_info_dict = info_dict;
# v = Video(path=filepathsafe);
# video_dict=v.toDictionary();
# self.setVersionInfo(video_path = filepathsafe, version_label=max_height, num_frames_total=v.num_frames_total, **video_dict);
# self.save();
self.addVersion(path=filepathsafe, version_label=max_height);
return self.getVersionPath(version_label=max_height);
# return youtube_link;
================================================
FILE: src/video2npz/visbeat3/visbeat3/Video_CV.py
================================================
# from Video import *
from .Image import *
from .Event import *
from .VisualBeat import *
import librosa
FEATURE_FUNCS = {};
VIS_FUNCS = {};
VISVIDEO_FUNCS = {};
FLOW_LOG_EPSILON=1.0;
FLOW_UNIT_GAIN=10000.0;
HISTOGRAM_FRAMES_PER_BEAT = 2;
HISTOGRAM_DOWNSAMPLE_LEVELS = 3;
VB_UPSAMPLE_FACTOR = 1.0;
USING_OPENCV = Image.USING_OPENCV;
if(USING_OPENCV):
##########################################################################
# ################ THESE ARE THE FUNCTIONS TO OVERRIDE! ################ #
# ################ FOR CUSTOM SALIENCY METRICS! ################ #
##########################################################################
# You can modify them here. But I would suggest elsewhere in your code
# just setting Video.localRhythmicSaliencyFunction and
# Video.visualBeatFunction to whatever you want. See how they are assigned
# when Video_CV is included in Video.py. -Abe
def localRhythmicSaliencyFunction(self, **kwargs):
"""
Change to use different function for local saliency
"""
return self.getVisibleImpactEnvelope(**kwargs);
def visualBeatFunction(self, **kwargs):
"""
Change to use different default strategy for selecting visual beats
"""
# beat_params = dict(
# pre_max_time=0.2,
# post_max_time=0.2,
# pre_avg_time=0.2,
# post_avg_time=0.2,
# wait_time=0.1,
# )
beat_params = self._getDefaultPeakPickingTimeParams();
beat_params.update(kwargs);
return self.getVisibleImpacts(**beat_params);
# #################### This is how they are called #################### #
def getLocalRhythmicSaliency(self, force_recompute=False, **kwargs):
feature_name = 'local_rhythmic_saliency';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = dict();
params.update(kwargs);
params.update({'force_recompute':force_recompute});
result = self.localRhythmicSaliencyFunction(**params);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getVisualBeats(self, force_recompute=False, **kwargs):
feature_name = 'visual_beats';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
params.update({'force_recompute': force_recompute});
result = self.visualBeatFunction(**params);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
# ##################################################################### #
##########################################################################
# ###################################################################### #
##########################################################################
def cvGetGrayFrame(self, f):
colorframe = self.getFrame(f).astype(np.uint8);
return ocv.cvtColor(colorframe, ocv.COLOR_RGB2GRAY);
def getImageFromFrameGray(self, f):
frame = self.getImageFromFrame(f);
frame.RGB2Gray();
return frame;
def flow2row(ang, amp, bins, subdivs, n_shifts, density):
h, w = ang.shape[:2];
ncells = np.power(4, subdivs);
nperd = np.power(2, subdivs);
xw = w-n_shifts[1];
yw = h-n_shifts[0];
xcells = np.arange(nperd + 1, dtype=float);
ycells = np.arange(nperd + 1, dtype=float);
xcells = np.floor((xcells / (nperd)) * xw);
ycells = np.floor((ycells / (nperd)) * yw);
# print(n_shifts)
ahis = np.zeros([ncells * bins, n_shifts[0]*n_shifts[1]]);
for dy in range(n_shifts[0]):
for dx in range(n_shifts[1]):
ampwin = amp[dy:dy+yw,dx:dx+xw];
angwin = ang[dy:dy+yw,dx:dx+xw];
cell_counter = 0;
for x in range(nperd):
for y in range(nperd):
ystart=int(ycells[y]);
yend = int(ycells[y+1]);
xstart = int(xcells[x]);
xend = int(xcells[x + 1]);
angcell = angwin[ystart:yend, xstart:xend];
ampcell = ampwin[ystart:yend, xstart:xend];
cahis, cbinbounds = np.histogram(angcell.ravel(), bins=bins, range=(0, 2 * np.pi),
weights=ampcell.ravel(), density=density);
# print("ahis shape: {}\ncahis shape: {}\ndx, dy: {}, {}\ncell_counter: {}\nbins: {}\n".format(ahis.shape, cahis.shape, dx, dy, cell_counter, bins));
ahis[cell_counter * bins:(cell_counter + 1) * bins, dx+dy*n_shifts[0]] = cahis;
cell_counter = cell_counter + 1;
return ahis;
def getFlowFrame(self, frame_index):
prev_frame = self.cvGetGrayFrame(frame_index-1);
this_frame = self.vbGetGrayFrame(frame_index);
return cvDenseFlowFarneback(from_image=prev_frame, to_image=this_frame);
def getFlowFramePolar(self, frame_index):
"""
:param self:
:param frame_index:
:return: polar where polar[:,:,0] is amplitude, and polar[:,:,1] is angle
"""
flow = self.getFlowFrame(frame_index);
fx, fy = flow[:,:,0], flow[:,:,1];
polar = np.zeros(size(flow));
polar[:,:,0] = np.sqrt(fx * fx + fy * fy);
polar[:,:,1] = np.arctan2(fy, fx) + np.pi
return polar;
def computeDirectogramPowers(self, bins=None, dead_zone= 0.05, density=None, save_if_computed=True, noise_floor_percentile=None, **kwargs):
if(bins is None):
bins = 128;
if(noise_floor_percentile is None):
noise_floor_percentile = 20;
print(("Computing Flow Features with deadzone {}".format(dead_zone)))
signal_dim = 128;
m_histvals = np.zeros([signal_dim, self.n_frames(), 3]);
flow_averages = np.zeros([self.n_frames(), 1]);
sampling_rate=self.sampling_rate;
duration = self.getDuration();
nsamples = sampling_rate*duration;
# print(sampling_rate, duration)
frame_start_times = np.linspace(0,duration,num=int(nsamples),endpoint=False);
frame_index_floats = frame_start_times*self.sampling_rate;
lastframe = self.cvGetGrayFrame(frame_index_floats[0]);
start_timer=time.time();
last_timer=start_timer;
fcounter=0;
counter = 0;
for nf in range(len(frame_index_floats)):
nextframe= self.cvGetGrayFrame(frame_index_floats[nf]);
flow = cvDenseFlowFarneback(from_image=lastframe, to_image=nextframe);
h, w = flow.shape[:2];
fx, fy = flow[:,:,0], flow[:,:,1];
# if(filter_median):
# fx = fx-np.median(fx.ravel());
# fy = fy-np.median(fy.ravel());
# assert(False), "SHOULDNT BE FILTERING MEDIAN! VESTIGIAL CODE"
ang = np.arctan2(fy, fx) + np.pi
amp = np.sqrt(fx*fx+fy*fy);
winstarty = int(dead_zone*h);
winendy = h-winstarty;
winstartx = int(dead_zone*w);
winendx = w-winstartx;
angw = ang[winstarty:winendy, winstartx:winendx];
ampw = amp[winstarty:winendy, winstartx:winendx];
mask0 = (ampw>np.percentile(ampw,noise_floor_percentile)).astype(float);
ahis0, cbinbounds = np.histogram(angw.ravel(), bins=bins, range=(0, 2 * np.pi),
weights=mask0.ravel(), density=density);
ahis1, cbinbounds1 = np.histogram(angw.ravel(), bins=bins, range=(0, 2 * np.pi),
weights=ampw.ravel(), density=density);
ahis2, cbinbounds2 = np.histogram(angw.ravel(), bins=bins, range=(0, 2 * np.pi),
weights=np.power(ampw, 2).ravel(), density=density);
m_histvals[:, counter, 0] = ahis0;
m_histvals[:, counter, 1] = ahis1;
m_histvals[:, counter, 2] = ahis2;
lastframe=nextframe;
counter+=1;
fcounter+=1;
if(not (fcounter%50)):
if((time.time()-last_timer)>10):
last_timer=time.time();
print(("{}%% done after {} seconds...".format(100.0*truediv(fcounter,len(frame_index_floats)), last_timer-start_timer)));
params = dict( bins = bins,
deadzone=dead_zone,
density=density);
params.update(kwargs);
self.setFeature(name='directogram_powers', value=m_histvals, params=params);
if(save_if_computed):
self.save(features_to_save=['directogram_powers']);
return m_histvals;
######################### Other Features #############################
def getDirectogramPowers(self, force_recompute=False, **kwargs):
feature_name = 'directogram_powers';
if ((not self.hasFeature(feature_name)) or force_recompute):
flow_powers = self.computeDirectogramPowers(**kwargs);
return self.getFeature(feature_name);
# def getDirectogram(self, bins = None, weights=None, density=None, force_recompute=False, save_if_computed=True, **kwargs):
def getDirectogram(self, **kwargs):
feature_name = 'directogram';
force_recompute = kwargs.get('force_recompute');
if((not self.hasFeature(feature_name)) or force_recompute):
flow_powers = self.getFeature('directogram_powers');
fh = flow_powers[:,:,1];
self.setFeature(name='directogram', value=fh, params=kwargs);
return self.getFeature(feature_name);
def getVisualTempo(self, force_recompute=None, **kwargs):
feature_name = 'visual_tempo';
if ((not self.hasFeature(feature_name)) or force_recompute):
vbe = self.getFeature('local_rhythmic_saliency');
# assert librosa.__version__ == '0.7.1'
# result = librosa.beat.beat_track(onset_envelope=vbe, sr=self.sampling_rate, hop_length=1, **kwargs);
result = librosa.beat.beat_track(onset_envelope=vbe, sr=self.sampling_rate, hop_length=1, **kwargs);
self.setFeature(name=feature_name, value=result, params=kwargs);
return self.getFeature(feature_name);
def getVisualTempogram(self, window_length=None, force_recompute=None, norm_columns = None, **kwargs):
"""
:param self:
:param window_length: in seconds
:param force_recompute:
:param kwargs:
:return:
"""
feature_name = 'visual_tempogram';
if ((not self.hasFeature(feature_name)) or force_recompute):
if(window_length is None):
window_length = DEFAULT_TEMPOGRAM_WINDOW_SECONDS;
params = kwargs;
params.update({'force_recompute': force_recompute});
vbe = self.computeImpactEnvelope(cut_suppression_seconds = None);
onset_envelope = vbe;
win_length = int(round(window_length * self.sampling_rate));
sr = self.sampling_rate;
hop_length = 1;
center=kwargs.get('center');
if(center is None):
center=True;
window='hann'
norm=np.inf;
ac_window = librosa.filters.get_window(window, win_length, fftbins=True)
# Center the autocorrelation windows
n = len(onset_envelope)
if center:
onset_envelope = np.pad(onset_envelope, int(win_length // 2),
mode='linear_ramp', end_values=[0, 0])
# Carve onset envelope into frames
odf_frame = librosa.util.frame(onset_envelope,
frame_length=win_length,
hop_length=hop_length)
# Truncate to the length of the original signal
if center:
odf_frame = odf_frame[:, :n]
odf_frame = librosa.util.normalize(odf_frame,axis=0,norm=norm)
if(norm_columns is None):
norm_columns = True;
if(norm_columns):
# Window, autocorrelate, and normalize
result = librosa.util.normalize(
librosa.core.audio.autocorrelate(odf_frame * ac_window[:, np.newaxis], axis=0), norm=norm, axis=0);
else:
result = librosa.core.audio.autocorrelate(odf_frame * ac_window[:, np.newaxis], axis=0);
result = np.true_divide(result, np.max(result.ravel()));
tempo_bpms = librosa.tempo_frequencies(result.shape[0], hop_length=hop_length, sr=sr)
self.setFeature(name='tempogram_bpms', value=tempo_bpms);
###########
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getVisibleImpactEnvelope(self, force_recompute=False, **kwargs):
feature_name = 'impact_envelope';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result = self.computeImpactEnvelope(forward=True, backward = False, **kwargs);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getForwardVisibleImpactEnvelope(self, force_recompute=False, **kwargs):
"""
Same as getVisibleImpactEnvelope by default.
:param self:
:param force_recompute:
:param kwargs:
:return:
"""
feature_name = 'forward_visual_impact_envelope';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result = self.computeImpactEnvelope(forward=True, backward = False, **kwargs);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getBackwardVisibleImpactEnvelope(self, force_recompute=False, **kwargs):
feature_name = 'backward_visual_impact_envelope';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result = self.computeImpactEnvelope(forward=False, backward = True, **kwargs);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getBothWayVisibleImpactEnvelope(self, force_recompute=False, **kwargs):
feature_name = 'both_way_visual_impact_envelope';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result = self.computeImpactEnvelope(forward=True, backward = True, **kwargs);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getVisibleImpactEnvelopePowers(self, force_recompute=False, **kwargs):
feature_name = 'impact_envelope_powers';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
result0 = self.computeImpactEnvelope(power= 0, **params);
result = np.zeros([len(result0), 3]);
result[:, 0] = result0;
result[:, 1] = self.computeImpactEnvelope(power= 1, **params);
result[:, 2] = self.computeImpactEnvelope(power=2, **params);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getCutTimes(self):
return Event.ToStartTimes(self.getCutEvents());
def getCutEvents(self, force_recompute=False, **kwargs):
"""
Hacky estimate of cuts in a video
:param self:
:param force_recompute:
:param kwargs:
:return:
"""
feature_name = 'cut_events';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
powers = self.getFeature('directogram_powers');
im0 = powers[:, :, 0];
im2 = powers[:, :, 2];
imc = np.true_divide(im2, 0.05 + im0);
medsig = np.median(imc, 0);
medall = np.median(imc);
cutsig = np.true_divide(medsig, medall)
cut_detection_ratio = kwargs.get('cut_detection_ratio');
if(cut_detection_ratio is None):
cut_detection_ratio=CUT_DETECTION_RATIO;
clipsig = (cutsig > cut_detection_ratio).astype(float);
clip_floorsig = (cutsig > CUT_DETECTION_FLOOR).astype(float);
clipsig = np.multiply(clipsig, clip_floorsig);
einds = np.flatnonzero(clipsig);
etimes = einds * truediv(1.0, self.sampling_rate);
ev = Event.FromStartTimes(etimes, type='cut');
ev = self.visualBeatsFromEvents(ev);
evout = []
for e in range(len(ev)):
ev[e].setInfo('frame', einds[e]);
result = ev;
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def visualBeatsFromEvents(self, events):
def downsample_hist(sig, levels):
nperbin = np.power(2, levels);
rshp = sig.reshape(-1, nperbin);
return rshp.sum(axis=1);
if(self.hasFeature('impact_envelope')):
svbe=self.getFeature('impact_envelope');
else:
svbe=self.computeImpactEnvelope(cut_suppression_seconds = None);
flow_powers = self.getFeature('directogram_powers');
vis_tempogram = self.getFeature('visual_tempogram');
vbeats = [];
for e in events:
b = VisualBeat.FromEvent(e);
ei = int(round(b.start*self.sampling_rate*VB_UPSAMPLE_FACTOR));
b.weight = svbe[ei];
histsize = int(128/int(np.power(2,HISTOGRAM_DOWNSAMPLE_LEVELS)))
histslice = np.zeros([histsize, HISTOGRAM_FRAMES_PER_BEAT]);
histslice = np.squeeze(np.mean(histslice, 1));
b.flow_histogram = downsample_hist(sig=histslice, levels=HISTOGRAM_DOWNSAMPLE_LEVELS);
b.flow_histogram = np.divide(b.flow_histogram, np.sum(b.flow_histogram));
b.local_autocor = vis_tempogram[:,ei];
b.local_autocor = b.local_autocor/np.max(b.local_autocor);
b.sampling_rate=self.sampling_rate;
vbeats.append(b);
return vbeats;
def getVisualBeatTimes(self, **kwargs):
return Event.ToStartTimes(self.getVisualBeats(**kwargs));
def getDirectionalFlux(self,
f_sigma=None,
median_kernel=None,
power=None,
**kwargs):
"""
The visual impact complement of a spectral flux matrix
:param self:
:param f_sigma: sigma for the gaussian used to filter, using sp.ndimage.filters.gaussian_filter
:param median_kernel: used in sp.signal.medfilt
:param power: Which power of the flow to use. Usually use 1.
:param kwargs:
:return:
"""
def d_x(im):
d_im = np.zeros(im.shape);
d_im[:, 0] = im[:, 0];
for c in range(1, im.shape[1]):
d_im[:, c] = im[:, c] - im[:, c - 1];
return d_im;
if (f_sigma is None):
f_sigma = [5, 3];
if (median_kernel is None):
median_kernel = [3, 3];
if(power is None):
power = 1;
powers = self.getFeature('directogram_powers');
im = powers[:,:,power].copy();
if (f_sigma is not None):
im = sp.ndimage.filters.gaussian_filter(input=im, sigma=f_sigma, order=0);
im = sp.signal.medfilt(im, median_kernel);
return d_x(im);
def computeImpactEnvelope(self,
forward=True,
backward = False,
f_sigma=None,
median_kernel=None,
highpass_window_seconds= 0.8,
cut_percentile=99,
power=None,
crop = None,
normalize = True,
**kwargs):
"""
:param self:
:param forward: include impact going forward in time
:param backward: include impact going backward in time
:param f_sigma: sigma for the gaussian used to filter, using sp.ndimage.filters.gaussian_filter
:param median_kernel: used in sp.signal.medfilt
:param highpass_window_seconds: highpass window size in seconds
:param cut_percentile: percentile above which to consider cuts and to clip
:param power: Which power of the flow to use. Usually use 1.
:param crop:
:param kwargs:
:return:
"""
upsample_factor = kwargs.get('upsample_factor');
inputargs = dict(f_sigma=f_sigma,
median_kernel=median_kernel,
power=power,
crop = crop);
inputargs.update(kwargs);
im_d = self.getDirectionalFlux(**inputargs);
if(forward and backward):
im = np.fabs(im_d);
elif(forward):
im = -im_d;
im = np.clip(im, 0, None)
elif(backward):
im = im_d;
im = np.clip(im, 0, None)
else:
assert(False), "Must be at least one of either forward or backward."
vimpact = np.squeeze(np.mean(im, 0));
sampling_rate = self.sampling_rate;
if(upsample_factor is not None and (upsample_factor>1)):
newlen = upsample_factor * len(vimpact);
sampling_rate = upsample_factor*sampling_rate;
vimpact = sp.signal.resample(vimpact, newlen);
if(highpass_window_seconds):
order = kwargs.get('highpass_order');
if(order is None):
order = 5;
cutoff = truediv(1.0, highpass_window_seconds);
normal_cutoff = cutoff / (sampling_rate*0.5);
b, a = sp.signal.butter(order, normal_cutoff, btype='high', analog=False)
vimpact = sp.signal.filtfilt(b, a, vimpact);
normfactor = np.max(np.fabs(vimpact[:]));
if (cut_percentile is not None):
fx = np.fabs(vimpact);
pv = np.percentile(fx, cut_percentile);
pvlow = np.percentile(fx, cut_percentile-1);
normfactor = pv;
ptile = (vimpact > pv).astype(float);
pntile = (vimpact < -pv).astype(float);
pboth = ptile+pntile;
einds = np.flatnonzero(pboth);
lastind = -2;
for j in range(len(einds)):
if(einds[j]==(lastind+1)):
vimpact[einds[j]]=0;
else:
vimpact[einds[j]]=pvlow;
if(normalize):
vimpact = np.true_divide(vimpact, normfactor);
return vimpact;
# 0.8, cut_suppression_seconds = 0.4,
def computeImpactEnvelopeOld(self, f_sigma=None, median_kernel=None, highpass_window_seconds= 0.8, cut_percentile=99, power=None, crop = None, normalize=None, **kwargs):
"""
I believe this is the version of the function that I used in the original paper. Keeping it around for record.
:param self:
:param f_sigma:
:param median_kernel:
:param highpass_window_seconds:
:param cut_percentile:
:param power:
:param crop:
:param normalize:
:param kwargs:
:return:
"""
def d_x(im):
# d_im = np.zeros(im.shape, dtype=np.float128);
d_im = np.zeros(im.shape);
d_im[:, 0] = im[:, 0];
for c in range(1, im.shape[1]):
d_im[:, c] = im[:, c] - im[:, c - 1];
return d_im;
if (f_sigma is None):
f_sigma = [5, 3];
if (median_kernel is None):
median_kernel = [3, 3];
if(power is None):
power = 1;
upsample_factor = kwargs.get('upsample_factor');
powers = self.getFeature('directogram_powers');
print(("computing impact env with power {}".format(power)));
im = powers[:,:,power].copy();
if (f_sigma is not None):
im = sp.ndimage.filters.gaussian_filter(input=im, sigma=f_sigma, order=0);
im = sp.signal.medfilt(im, median_kernel);
im = -d_x(im);
im = np.clip(im, 0, None)
svbe = np.squeeze(np.mean(im, 0));
sampling_rate = self.sampling_rate;
if(upsample_factor is not None and (upsample_factor>1)):
newlen = upsample_factor * len(svbe);
sampling_rate = upsample_factor*sampling_rate;
svbe = sp.signal.resample(svbe, newlen);
if(highpass_window_seconds):
order = kwargs.get('highpass_order');
if(order is None):
order = 5;
cutoff = truediv(1.0, highpass_window_seconds);
normal_cutoff = cutoff / (sampling_rate*0.5);
b, a = sp.signal.butter(order, normal_cutoff, btype='high', analog=False)
svbe = sp.signal.filtfilt(b, a, svbe);
normfactor = np.max(np.fabs(svbe[:]));
if (cut_percentile is not None):
fx = np.fabs(svbe);
pv = np.percentile(fx, cut_percentile);
pvlow = np.percentile(fx, cut_percentile-1);
normfactor = pv;
ptile = (svbe > pv).astype(float);
pntile = (svbe < -pv).astype(float);
pboth = ptile+pntile;
einds = np.flatnonzero(pboth);
lastind = -2;
for j in range(len(einds)):
if(einds[j]==(lastind+1)):
svbe[einds[j]]=0;
else:
svbe[einds[j]]=pvlow;
if(normalize is not False):
svbe = np.true_divide(svbe, normfactor);
return svbe;
def getVisibleImpacts(self, force_recompute=False, include_cut_events = None, **kwargs):
feature_name = 'visible_impacts';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
svbe = self.getFeature('impact_envelope', **kwargs);
upsample_factor = kwargs.get('upsample_factor');
if(upsample_factor is None):
upsample_factor = 1;
u_sampling_rate = self.sampling_rate*upsample_factor;
peak_params = self._getDefaultPeakPickingTimeParams();
peak_params.update(kwargs); # if params given in arguments, those will override the defaults here.
v_events = Event.FromSignalPeaks(signal=svbe, sampling_rate=u_sampling_rate, **peak_params);
if(include_cut_events):
cut_events = self.getFeature('cut_events');
v_events = v_events + cut_events;
Event.Sort(v_events);
result = self.visualBeatsFromEvents(v_events);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getForwardVisibleImpacts(self, force_recompute=False, include_cut_events = None, **kwargs):
feature_name = 'forward_visual_beats';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
local_saliency = self.getFeature('forward_visual_impact_envelope', **kwargs);
upsample_factor = kwargs.get('upsample_factor');
if(upsample_factor is None):
upsample_factor = 1;
u_sampling_rate = self.sampling_rate*upsample_factor;
v_events = Event.FromSignalPeaks(signal=local_saliency, sampling_rate=u_sampling_rate, event_type= 'forward', **kwargs);
if(include_cut_events):
cut_events = self.getFeature('cut_events');
v_events = v_events + cut_events;
Event.Sort(v_events);
result = Event.SetDirections(v_events, direction=Event.DIRECTION_FORWARD);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def getBackwardVisibleImpacts(self, force_recompute=False, include_cut_events = None, **kwargs):
feature_name = 'backward_visual_beats';
if ((not self.hasFeature(feature_name)) or force_recompute):
params = kwargs;
local_saliency = self.getFeature('backward_visual_impact_envelope', **kwargs);
upsample_factor = kwargs.get('upsample_factor');
if(upsample_factor is None):
upsample_factor = 1;
u_sampling_rate = self.sampling_rate*upsample_factor;
v_events = Event.FromSignalPeaks(signal=local_saliency, sampling_rate=u_sampling_rate, **kwargs);
if(include_cut_events):
cut_events = self.getFeature('cut_events');
v_events = v_events + cut_events;
Event.Sort(v_events);
# result = self.visualBeatsFromEvents(v_events);
result = Event.SetDirections(v_events, direction=Event.DIRECTION_BACKWARD);
self.setFeature(name=feature_name, value=result, params=params);
return self.getFeature(feature_name);
def findAccidentalDanceSequences(self, target_n_beats = 7, n_samples=25, delta_range = None):
if(delta_range is None):
delta_range = [0.02, 0.5];
deltas = np.linspace(delta_range[0], delta_range[1], num=n_samples, endpoint=True);
deltapick = delta_range[0];
sequences = [];
for i, delta in enumerate(deltas):
peak_vars = self._getDefaultPeakPickingTimeParams(delta=delta);
sequences = self.getVisualBeatSequences(peak_vars=peak_vars, print_summary=False);
# print("Delta {} has top sequence with {} beats".format(delta, len(sequences[0])));
if(len(sequences[0])<=target_n_beats):
deltapick = delta;
break;
print(("Selected delta value {}".format(deltapick)));
return sequences;
def getVisualBeatSequences(self,
search_tempo=None,
target_period=None,
search_window=0.75,
min_beat_limit=None,
max_beat_limit=None,
unary_weight=None,
binary_weight=None,
break_on_cuts=None,
peak_vars=None,
time_range=None,
n_return = None,
unsorted = False,
print_summary = True,
**kwargs):
"""
:param self:
:param search_tempo: optional tempo you would like to find visual beats at
:param target_period: optional target period you would like to use for finding beats. Ignored if search tempo is provided.
:param search_window: longest amount of time (seconds) allowed between beats before a segment is broken into multiple segments
:param min_beat_limit: only consider sequences with
:param unary_weight:
:param binary_weight:
:param break_on_cuts:
:param peak_vars:
:param kwargs:
:return:
"""
if (peak_vars is not None):
# impacts = self.getFeature('visible_impacts', force_recompute=True, **peak_vars);
impacts = self.getVisualBeats(force_recompute = True, **peak_vars);
else:
# impacts = self.getFeature('visible_impacts');
impacts = self.getVisualBeats();
if(time_range is not None):
impactseg = [];
for i in impacts:
if(i.start>time_range[0] and i.start < time_range[1]):
impactseg.append(i);
impacts = impactseg;
if (search_tempo is not None):
tempo = search_tempo;
beat_time = np.true_divide(60.0, tempo);
sequences = VisualBeat.PullOptimalPaths_Basic(impacts, target_period=beat_time, unary_weight=unary_weight,
binary_weight=binary_weight, break_on_cuts=break_on_cuts,
window_size=search_window);
elif(target_period is not None):
sequences = VisualBeat.PullOptimalPaths_Basic(impacts, target_period=target_period, unary_weight=unary_weight,
binary_weight=binary_weight, break_on_cuts=break_on_cuts,
window_size=search_window);
else:
sequences = VisualBeat.PullOptimalPaths_Autocor(impacts, unary_weight=unary_weight, binary_weight=binary_weight,
break_on_cuts=break_on_cuts, window_size=search_window);
r_sequences = [];
if(min_beat_limit is None):
min_beat_limit = 2;
if(max_beat_limit is None):
max_beat_limit = len(impacts)+1;
for S in sequences:
if ((len(S) > min_beat_limit) and (len(S) < max_beat_limit)):
r_sequences.append(S);
if(not unsorted):
r_sequences.sort(key=len, reverse=True);
if(n_return is not None):
r_sequences = r_sequences[:n_return];
if(print_summary):
print(("{} segments".format(len(r_sequences))));
for s in range(len(r_sequences)):
print(("Segment {} has {} beats".format(s, len(r_sequences[s]))));
return r_sequences;
def printVisualBeatSequences(self,
search_tempo=None,
target_period=None,
search_window=None,
min_beat_limit=None,
max_beat_limit=None,
unary_weight=None,
binary_weight=None,
break_on_cuts=None,
peak_vars=None,
n_return = None,
time_range=None, **kwargs):
"""
:param self:
:param target_period:
:param search_tempo:
:param search_window:
:param beat_limit:
:param unary_weight:
:param binary_weight:
:param break_on_cuts:
:param n_return:
:param peak_vars:
:param time_range:
:param kwargs:
:return:
"""
sorted = True;
sequence_args = dict(
search_tempo=search_tempo,
target_period=target_period,
search_window=search_window,
min_beat_limit=min_beat_limit,
max_beat_limit=max_beat_limit,
unary_weight=unary_weight,
binary_weight=binary_weight,
break_on_cuts=break_on_cuts,
peak_vars=peak_vars,
n_return=n_return,
time_range=time_range);
seqs = self.getVisualBeatSequences(**sequence_args)
print(("sequence arguments were:\n{}".format(sequence_args)));
print(("There were {} sequences total".format(len(seqs))));
nclips = 0;
rsegments = [];
for S in seqs:
if (len(S) > 1):
nclips = nclips + 1;
rsegments.append(S);
# rsegments.sort(key=len, reverse=True);
# if (n_return is not None):
# rsegments = rsegments[:n_return];
Event.PlotSignalAndEvents(self.getFeature('impact_envelope'), sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=rsegments[0], time_range=time_range);
return rsegments;
def plotEvents(self, events, time_range = 'default', **kwargs):
time_range_use = time_range;
if(time_range.lower() == 'default'):
time_range_use = [0,0];
time_range_use[0] = events[0].start-1;
time_range_use[1] = events[-1].start+1;
signal = self.getFeature('local_rhythmic_saliency');
mplt = Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate * VB_UPSAMPLE_FACTOR, events=events, time_range=time_range_use, **kwargs);
plt.xlabel('Time (s)')
return mplt;
def plotCutEvents(self, **kwargs):
signal = self.getFeature('impact_envelope');
events = self.getFeature('cut_events', **kwargs);
Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=events, **kwargs);
def plotVisibleImpacts(self, **kwargs):
signal = self.getFeature('impact_envelope');
events = self.getFeature('visible_impacts', **kwargs);
Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=events, **kwargs);
plt.title('Impact Envelope & Visual Beats')
plt.xlabel('Time (s)')
plt.ylabel('Impact Strength')
def plotImpactEnvelope(self, **kwargs):
signal = self.getFeature('local_rhythmic_saliency');
# events = self.getFeature('visual_beats', **kwargs);
events = None;
Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=events, **kwargs);
plt.title('Impact Envelope & Visual Beats')
plt.xlabel('Time (s)')
plt.ylabel('Impact Strength')
def plotVisualBeats(self, **kwargs):
signal = self.getFeature('local_rhythmic_saliency');
events = self.getFeature('visual_beats', **kwargs);
Event.PlotSignalAndEvents(signal, sampling_rate=self.sampling_rate*VB_UPSAMPLE_FACTOR, events=events, **kwargs);
plt.title('Impact Envelope & Visual Beats')
plt.xlabel('Time (s)')
plt.ylabel('Impact Strength')
def loadFlowFeatures(self):
self.load(features_to_load=['directogram_powers', 'directogram']);
FEATURE_FUNCS['local_rhythmic_saliency'] = getLocalRhythmicSaliency;
FEATURE_FUNCS['directogram_powers'] = getDirectogramPowers;
FEATURE_FUNCS['directogram'] = getDirectogram;
FEATURE_FUNCS['impact_envelope'] = getVisibleImpactEnvelope;
FEATURE_FUNCS['impact_envelope_powers'] = getVisibleImpactEnvelopePowers;
FEATURE_FUNCS['visible_impacts'] = getVisibleImpacts;
FEATURE_FUNCS['visual_beats'] = getVisualBeats;
# FEATURE_FUNCS['backward_visual_beats'] = getBackwardVisualBeats;
# FEATURE_FUNCS['forward_visual_beats'] = getForwardVisualBeats;
FEATURE_FUNCS['backward_visual_impact_envelope'] = getBackwardVisibleImpactEnvelope;
FEATURE_FUNCS['both_way_visual_impact_envelope'] = getBothWayVisibleImpactEnvelope;
FEATURE_FUNCS['forward_visual_impact_envelope'] = getForwardVisibleImpactEnvelope;
FEATURE_FUNCS['directional_flux'] = getDirectionalFlux;
FEATURE_FUNCS['visual_tempogram'] = getVisualTempogram;
FEATURE_FUNCS['cut_events']=getCutEvents;
================================================
FILE: src/video2npz/visbeat3/visbeat3/VisBeatDefines.py
================================================
VB_DEBUG = True;
DEFAULT_TEMPOGRAM_WINDOW_SECONDS = 5;
AUDIO_DEFAULT_HOP_LENGTH = 512;
================================================
FILE: src/video2npz/visbeat3/visbeat3/VisBeatExampleVideo.py
================================================
import os
from visbeat3.SourceLocationParser import ParseSourseLocation
class VisBeatExampleVideo(object):
def __init__(self, name, url, start_beat=None, end_beat = None, display_name = None, code=None, leadin=None, **kwargs):
self.name = name;
self.url = url;
self.start_beat = start_beat;
self.end_beat = end_beat;
self._display_name = display_name;
self._code = code;
self.leadin = leadin;
for k in kwargs:
setattr(self, k, kwargs[k]);
if(code is None):
sloc = ParseSourseLocation(self.url);
self._code = sloc.code;
#
@property
def code(self):
return self._getCode();
def _getCode(self):
return self._code;
@code.setter
def code(self, value):
self._setCode(value);
def _setCode(self, value):
self._code = value;
#
# def _ytEmbedCode(self):
#
@property
def display_name(self):
return self._getDisplayName();
def _getDisplayName(self):
if(self._display_name is None):
return self.name;
else:
return self._display_name;
#
def _ytWatchURL(self):
return 'https://www.youtube.com/watch?v={}'.format(self.code);
def _ytEmbedURL(self, autoplay=None):
s = 'https://www.youtube.com/embed/{}'.format(self.code);
if(autoplay):
s = s+'?autoplay=1';
return s;
def _ytThumbURL(self):
return 'https://ytimg.googleusercontent.com/vi/{}/default.jpg'.format(self.code);
def _fancyBoxCode(self, with_label = None):
""""""
s = HTMLCode();
if(with_label):
s.addLine("")
s.addLine('
'.format(watchurl=self._ytWatchURL(),
alt_name = self.display_name,
thumburl = self._ytThumbURL()))
if(with_label):
s.addLine('');
# s.addLine('{displayname}'.format(self.url, self.display_name));
s.addLine('{displayname}'.format(displayname=self.display_name));
s.addLine(' ')
s.addLine(' ');
return s.string;
from bs4 import BeautifulSoup
class HTMLCode(object):
def __init__(self, start_string=None):
self._code = "";
self._lines = [];
if(start_string is not None):
self.add(start_string)
self._soup = None;
#
@property
def string(self):
return self._getString();
def _getString(self):
return BeautifulSoup(self.code).prettify();
#
@property
def code(self):
return self._getCode();
def _getCode(self):
return self._code;
@code.setter
def code(self, value):
self._setCode(value);
def _setCode(self, value):
self._code = value;
#
#
@property
def soup(self):
return self._getSoup();
def _getSoup(self):
if(self._soup is None):
self._makeSoup();
return self._soup;
def _makeSoup(self):
self._soup = BeautifulSoup(self.code, 'html.parser');
# @soup.setter
# def soup(self, value):
# self._setSoup(value);
# def _setSoup(self, value):
# self._soup = value;
#
def add(self, s):
self.code = self.code+s;
def addLine(self, s):
self.code = self.code+'\n'+s;
def startTable(self, id=None, class_ = None, **kwargs):
targs = dict(table_width="80%", border=1, cellspacing=1, cellpadding=1)
targs.update(kwargs);
s = ''.format(**targs);
self.addLine(s);
self.addLine('');
def endTable(self):
self.addLine("");
self.addLine("
");
def startRow(self):
self.addLine('');
def endRow(self):
self.addLine(' ');
def addColumnLabel(self, label):
self.addLine('')
self.addLine(label);
self.addLine(' ');
def addRowLabel(self, label):
self.addLine('')
self.addLine(label);
self.addLine(' ');
def addRowCell(self, content):
self.addLine("");
self.addLine("")
self.addLine(content);
self.addLine("")
self.addLine(" ");
================================================
FILE: src/video2npz/visbeat3/visbeat3/VisBeatImports.py
================================================
from .VisBeatDefines import *
from .AImports import *
from .AObject import AObject
import numpy as np
import scipy as sp
import os
import imageio
import matplotlib
try:
import matplotlib.pyplot as plt
except ImportError as e:
AWARN("matplotlib problem... if you are using conda try installing with 'conda install matplotlib'")
matplotlib.use('agg');
import matplotlib.pyplot as plt
import matplotlib.style as ms
import io
import base64
import math
from operator import truediv
import time
import shutil
from time import gmtime, strftime, localtime
import librosa;
from ._mediafiles import GetVBMarkPath
def local_time_string():
return strftime("%Y-%m-%d_%H:%M:%S", localtime());
def VBWARN(message):
print(message)
#
# def send_warnings_to_print_red(message, category, filename, lineno):
# print(colored('{} WARNING! file: {} Line:{}\n{}'.format(category, filename, lineno, message), 'red'))
# old_showwarning = warnings.showwarning
# warnings.showwarning = send_warnings_to_print_red;
VB_MACHINE_ID = None;
# if(VB_MACHINE_ID):
# matplotlib.use('PS');
ISNOTEBOOK = False;
if(runningInNotebook()):
ISNOTEBOOK = True;
import IPython;
import IPython.display
ms.use('seaborn-muted')
if(not runningInSpyder()):
get_ipython().magic('matplotlib inline')
from IPython.lib import kernel
connection_file_path = kernel.get_connection_file()
connection_file = os.path.basename(connection_file_path)
kernel_id = connection_file.split('-', 1)[1].split('.')[0]
# print("Kernel ID:\n{}".format(kernel_id));
from IPython.display import HTML
VBIPY = IPython;
#%matplotlib inline
# else:
# matplotlib.use('PS');
def vb_get_ipython():
return VBIPY;
def clipping_params(clip_bins=30, clip_fraction=0.95):
return dict(clip_bins=clip_bins, clip_fraction=clip_fraction);
def get_hist_clipped(signal, clip_bins=30, clip_fraction=0.95):
holdshape = signal.shape[:];
sigrav = signal.copy().ravel();
sigh, sigb = np.histogram(sigrav, bins=clip_bins);
maxbini=np.argmax(sigh);
totalmass = np.sum(sigh);
total_included = truediv(sigh[maxbini],totalmass);
prevbini = maxbini;
nextbini=maxbini;
bins_included = 1;
icounter=0;
while(total_included=0 and sigh[prevbini]==0) and (nextbini<(clip_bins) and sigh[nextbini]==0)):
prevbini=prevbini-1;
nextbini=nextbini+1;
else:
if((prevbini>=0 and sigh[prevbini]>0) or nextbini>=clip_bins):
prevbini=prevbini-1;
if((nextbini<(clip_bins) and sigh[nextbini]>0) or prevbini<0):
nextbini=nextbini+1;
included_segment=sigh[max(prevbini,0):min(nextbini+1, clip_bins)];
total_included = truediv(np.sum(included_segment), totalmass);
bins_included=len(included_segment);
icounter+=1;
clipsig = np.clip(a=sigrav, a_min=sigb[max(prevbini,0)], a_max=sigb[min(nextbini,clip_bins)]);
clipsig.shape=signal.shape
return clipsig;
def np_scale_to_range(data, value_range=None):
if(value_range is None):
value_range = [0.0,255.0];
d = data.copy().ravel();
currentmin=np.min(d);
currentmax=np.max(d);
currentscale = currentmax-currentmin;
if(currentscale==0):
VBWARN("CANNOT SCALE CONSTANT ARRAY TO RANGE")
return;
divscale = truediv(1.0,currentscale);
newrange=(value_range[1]-value_range[0]);
d = (d*divscale)*newrange;
newmin = (currentmin*divscale)*newrange;
d = d-newmin+value_range[0]
d.shape=data.shape;
return d
================================================
FILE: src/video2npz/visbeat3/visbeat3/VisualBeat.py
================================================
from .Event import *
class VisualBeat(Event):
def VBOBJECT_TYPE(self):
return 'VisualBeat';
def __init__(self, start=None, type=None, weight=None, index=None, unrolled_start = None, direction=0):
Event.__init__(self, start=start, type=type, weight=weight, index=index, unrolled_start=unrolled_start, direction=direction);
def initializeBlank(self):
Event.initializeBlank(self);
self.flow_histogram = None;
self.local_autocor = None;
self.sampling_rate = None;
def __str__(self):
return "start:{}\ntype:{}\nweight:{}\nindex:{}\nunrolled_start:{}\nis_active:{}\n".format(self.start, self.type, self.weight, self.index, self.unrolled_start, self.is_active);
# def toGUIDict(self, is_active=1):
# return dict(start=self.start, index=self.index, is_active=None)
def toDictionary(self):
d=Event.toDictionary(self);
# d['start']=self.start;
# d['type']=self.type;
# d['weight']=self.weight;
# d['index']=self.index;
# d['unrolled_start']=self.unrolled_start;
d['flow_histogram']=self.flow_histogram;
d['local_autocor']=self.local_autocor;
d['sampling_rate']=self.sampling_rate;
return d;
def initFromDictionary(self, d):
Event.initFromDictionary(self, d);
self.start = d['start'];
self.type = d['type'];
self.weight = d['weight'];
self.index = d['index'];
self.unrolled_start = d['unrolled_start'];
self.flow_histogram = d.get('flow_histogram');
self.local_autocor = d.get('local_autocor');
self.sampling_rate = d.get('sampling_rate');
def clone(self, start=None):
if(start):
newv = VisualBeat(start = start, type=self.type, weight=self.weight, index=self.index);
else:
newv = VisualBeat(start = self.start, type=self.type, weight=self.weight, index=self.index);
newv.flow_histogram = self.flow_histogram.copy();
newv.local_autocor = self.local_autocor.copy();
newv.sampling_rate = self.sampling_rate;
return newv;
@staticmethod
def FromEvent(e):
if(isinstance(e,VisualBeat)):
return e.clone();
else:
return VisualBeat(start=e.start, type=e.type, weight=e.weight, index=e.index);
@staticmethod
def time_window_func(max_separation, break_on_cuts=None):
def window_func(a, b):
if(break_on_cuts and (a.type=='cut' or b.type=='cut')):
return False;
if(np.fabs(a.start-b.start)3.75):
score=-1;
return binary_weight*score;
return objective_func;
@staticmethod
def angle_binary_objective(binary_weight=None, absolute=None):
if (binary_weight is None):
binary_weight = 1.0;
# if (angle_weight is None):
# angle_weight = 0.0;
def objective_func(a, b):
# T = np.fabs(a.start - b.start);
# tempo_score = -np.power(np.log(truediv(T, target_period)), 2.0) * binary_weight;
# should mask out unary contribution from orthogonal angles
if(absolute):
return binary_weight * (np.fabs(np.dot(a.flow_histogram, b.flow_histogram)) - 0.70710678118); # cos 45 degrees
else:
return binary_weight * (np.dot(a.flow_histogram, b.flow_histogram)); # cos 45 degrees
return objective_func;
@staticmethod
def Double(events, type=None):
doubled = [];
for e in range(1, len(events)):
halfstart = 0.5 * (events[e].start + events[e - 1].start);
newhevent = events[e].clone(start=halfstart);
if(type is not None):
newhevent.type = type;
doubled.append(newhevent);
doubled.append(events[e]);
return doubled;
@staticmethod
def weight_unary_objective(unary_weight=None):
if(unary_weight is None):
unary_weight = 1.0;
def getweight_func(b):
return unary_weight*b.weight;
return getweight_func;
@staticmethod
def PullOptimalPaths_Basic(vis_beats, target_period, unary_weight=None, binary_weight=None, window_size=None, break_on_cuts = None):
if(window_size is None):
window_size = DEFAULT_WINDOW_FACTOR*target_period;
binary_objective = VisualBeat.tempo_binary_objective(target_period=target_period, binary_weight = binary_weight);
unary_objective = VisualBeat.weight_unary_objective(unary_weight=unary_weight);
window_function = VisualBeat.time_window_func(max_separation = window_size, break_on_cuts=break_on_cuts);
return VisualBeat.DynamicProgramOptimalPaths(vis_beats=vis_beats,
unary_objective_func=unary_objective,
binary_objective_func=binary_objective,
window_func=window_function);
@staticmethod
def PullOptimalPaths(vis_beats, unary_fn=None, binary_fn=None, window_fn=None, target_period=None, unary_weight=None, binary_weight=None, window_size=None,
break_on_cuts=None):
if (window_size is None):
window_size = DEFAULT_WINDOW_FACTOR * target_period;
if(binary_fn == 'autocor'):
binary_objective = VisualBeat.autocor_binary_objective(binary_weight=binary_weight);
elif(binary_fn == 'angle'):
binary_objective = VisualBeat.angle_binary_objective(binary_weight=binary_weight);
else:
binary_objective = VisualBeat.tempo_binary_objective(target_period=target_period, binary_weight=binary_weight);
unary_objective = VisualBeat.weight_unary_objective(unary_weight=unary_weight);
window_function = VisualBeat.time_window_func(max_separation=window_size, break_on_cuts=break_on_cuts);
return VisualBeat.DynamicProgramOptimalPaths(vis_beats=vis_beats,
unary_objective_func=unary_objective,
binary_objective_func=binary_objective,
window_func=window_function);
@staticmethod
def PullOptimalPaths_Autocor(vis_beats, unary_weight=None, binary_weight=None, window_size=None,
break_on_cuts=None, **kwargs):
if (window_size is None):
# assert(False), 'no window size provided'
# window_size = DEFAULT_WINDOW_FACTOR * target_period;
window_size = 200;
AWARN('NO WINDOWSIZE PROVIDED! PullOptimalPaths_Autocor');
binary_objective = VisualBeat.autocor_binary_objective(binary_weight=binary_weight);
unary_objective = VisualBeat.weight_unary_objective(unary_weight=unary_weight);
window_function = VisualBeat.time_window_func(max_separation=window_size, break_on_cuts=break_on_cuts);
return VisualBeat.DynamicProgramOptimalPaths(vis_beats=vis_beats,
unary_objective_func=unary_objective,
binary_objective_func=binary_objective,
window_func=window_function);
@staticmethod
def DynamicProgramOptimalPaths(vis_beats, unary_objective_func, binary_objective_func, window_func):
class Node(object):
def __init__(self, object, prev_node=None):
self.object = object;
self.prev_node = prev_node;
self.cum_score=None;
nodes = [];
beats = Event.GetSorted(vis_beats);
Event.ApplyIndices(beats);
for b in beats:
nodes.append(Node(object=b));
nodes[0].prev_node = None;
nodes[0].cum_score = unary_objective_func(nodes[0].object);
current_segment = [];
segments = [];
for n in range(1,len(nodes)):
current_node = nodes[n];
current_segment.append(current_node);
options = [];
j = n-1;
while(j>=0 and window_func(current_node.object,nodes[j].object)):
options.append(nodes[j]);
j = j-1;
if(len(options)==0):
current_node.prev_node=None;
current_node.cum_score=unary_objective_func(current_node.object);
segments.append(current_segment);
current_segment = [];
else:
best_choice = options[0];
best_score = options[0].cum_score+binary_objective_func(current_node.object, best_choice.object);
for o in range(1,len(options)):
score = options[o].cum_score+binary_objective_func(current_node.object, options[o].object);
if(score>best_score):
best_choice=options[o];
best_score=score;
current_node.prev_node = best_choice;
current_node.cum_score = best_score+unary_objective_func(current_node.object);
if(len(current_segment)>0):
segments.append(current_segment);
sequences = [];
for S in segments:
seq = [];
max_node = S[0];
max_score = max_node.cum_score;
for n in range(len(S)):
if(S[n].cum_score>max_score):
max_node = S[n];
max_score = max_node.cum_score;
trace_node = max_node;
while(trace_node.prev_node is not None):
seq.append(trace_node.object);
trace_node=trace_node.prev_node;
seq.reverse();
sequences.append(seq);
return sequences;
================================================
FILE: src/video2npz/visbeat3/visbeat3/Warp.py
================================================
from .VisBeatImports import *
from .EventList import *
import math
DEFAULT_LEAD_TIME = 0;
DEFAULT_TAIL_TIME = 0;
class Warp(AObject):
"""Warp (class): defines how one time signal should be warped to another. Given primarily as source/target events to be matched.
Attributes:
source_events: source events
target_events: target events
"""
def VBOBJECT_TYPE(self):
return 'Warp';
def __init__(self, path=None):
AObject.__init__(self, path=path);
if(path):
self.loadFile();
@staticmethod
def FromEvents(source_events, target_events):
w = Warp();
sevents = source_events;
if(isinstance(source_events, EventList)):
sevents = source_events.events;
tevents = target_events;
if(isinstance(target_events, EventList)):
tevents = target_events.events;
w.source_events=sevents;
w.target_events=tevents;
# w.repeatShorterEvents();
return w
@staticmethod
def FromEventLists(source_eventlist, target_eventlist):
w = Warp();
w.source_events = source_eventlist.events;
w.target_events = target_eventlist.events;
# w.repeatShorterEvents();
return w
def initializeBlank(self):
AObject.initializeBlank(self);
self.source_events = [];
self.target_events = [];
# self.a_info['WarpType'] = 'Linear';
self.warp_func = None; # Warp.LinearInterp;
# self.warp_func_st = None;
# self.warp_func_ts = None;
def getTargetStart(self, lead=None):
target_start = self.target_events[0].getStartTime();
if (lead is None):
lead = min(target_start, DEFAULT_LEAD_TIME);
return target_start - lead;
def getTargetEnd(self, lead=None):
lastind = min(len(self.source_events), len(self.target_events)) - 1;
return self.target_events[lastind].getStartTime() + DEFAULT_TAIL_TIME;
def getSourceStart(self):
source_start = self.source_events[0].getUnrolledStartTime();
return source_start;
def getSourceEnd(self):
lastind = min(len(self.source_events), len(self.target_events)) - 1;
return self.source_events[lastind].getUnrolledStartTime();
def getWarpedSourceStart(self, lead=None):
source_start = self.source_events[0].getUnrolledStartTime();
if (lead is None):
lead = min(source_start, DEFAULT_LEAD_TIME);
return self.warpSourceTime(source_start - lead);
def getWarpedSourceEnd(self, tail=None):
last_event = min(len(self.source_events), len(self.target_events)) - 1;
source_end = self.source_events[last_event].getUnrolledStartTime();
if (tail is None):
tail = DEFAULT_TAIL_TIME;
source_end = source_end + tail;
return self.warpSourceTime(source_end);
def setWarpFunc(self, warp_type, **kwargs):
if (warp_type == 'square'):
self.warp_func = [Warp.SquareInterp, Warp.SquareInterp];
elif (warp_type == 'linear'):
self.warp_func = [Warp.LinearInterp, Warp.LinearInterp];
elif (warp_type == 'cubic'):
self.warp_func = [Warp.CubicInterp, Warp.CubicInterp];
elif (warp_type == 'quad'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events, Warp.WFunc_Quadratic(), **kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events, Warp.WFunc_Quadratic(), **kwargs)];
elif (warp_type == 'mouth'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events, Warp.WFunc_Mouth(**kwargs), **kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events, Warp.WFunc_Mouth(**kwargs), **kwargs)];
elif (warp_type == 'weight'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events,
Warp.WFunc_Weight(use_to_weights=None, **kwargs), **kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events,
Warp.WFunc_Weight(use_to_weights=True, **kwargs), **kwargs)];
elif (warp_type == 'half_accel'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events, Warp.WFunc_P(p=0.5),
**kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events, Warp.WFunc_P(p=0.5),
**kwargs)];
elif (warp_type == 'p'):
p = kwargs.get('p');
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events, Warp.WFunc_P(p=p),
**kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events, Warp.WFunc_P(p=p),
**kwargs)];
elif (warp_type == 'target_time_source_fraction'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events,
Warp.WFunc_targettime_sourcefraction(**kwargs),
**kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events,
Warp.WFunc_targettime_sourcefraction(**kwargs),
**kwargs)];
elif (warp_type == 'target_source_fractions'):
self.warp_func = [
Warp.GetEventWarpFunc(self.source_events, self.target_events,
Warp.WFunc_target_source_fractions(**kwargs),
**kwargs),
Warp.GetEventWarpFunc(self.target_events, self.source_events,
Warp.WFunc_target_source_fractions(**kwargs),
**kwargs)];
elif (warp_type is not None):
self.warp_func = [warp_type, warp_type];
self.setInfo('WarpType', warp_type);
return;
def warpSourceTime(self, t):
return self.warp_func[0](t, a_events=self.source_events, b_events=self.target_events);
def warpSourceTimes(self, t):
tw = t.copy();
for a in range(len(t)):
tw[a] = self.warpSourceTime(t[a]);
return tw;
def warpTargetTime(self, t):
return self.warp_func[1](t, a_events=self.target_events, b_events=self.source_events);
def warpTargetTimes(self, t):
tw = t.copy();
for a in range(len(t)):
tw[a] = self.warpTargetTime(t[a]);
return tw;
def plot(self, xlim=None, sampling_rate=None, new_figure=None, render_control_points=True, render_labels=True,
time_range=None, full_source_range=None, **kwargs):
if (sampling_rate is None):
sampling_rate = 30;
source_duration = self.getSourceEnd() - self.getSourceStart();
old_frame_time = truediv(1.0, sampling_rate);
target_start = self.getTargetStart();
target_end = self.getTargetEnd();
# if(xlim is not None):
# target_start=xlim[0]
target_duration = target_end - target_start;
new_n_samples = target_duration * sampling_rate;
target_start_times = np.linspace(target_start, target_end, num=new_n_samples, endpoint=False);
unwarped_target_times = [];
for st in target_start_times:
unwarped_target_times.append(self.warpTargetTime(st));
if (new_figure):
fig = plt.figure();
unwarped_target_times = np.array(unwarped_target_times);
# unwarped_target_times = unwarped_target_times-unwarped_target_times[0]+target_start;
plt.plot(target_start_times, unwarped_target_times, '-');
if (render_control_points):
lastind = min(len(self.source_events), len(self.target_events)) - 1;
targeteventtimes = Event.ToStartTimes(self.target_events[:lastind]);
sourceeventtimes = Event.ToStartTimes(self.source_events[:lastind]);
plt.plot(targeteventtimes, sourceeventtimes, 'o', label='Control Points');
if (xlim is not None):
xrng = [xlim[0] + target_start, xlim[1] + target_start];
ylim = [self.warpTargetTime(xrng[0]), self.warpTargetTime(xrng[1])];
plt.xlim(xrng);
plt.ylim(ylim);
if (time_range is not None):
plt.xlim(time_range);
if (render_labels):
plt.ylabel('Source Time');
plt.xlabel('Target Time');
plt.title('Warp Curve')
if (new_figure is not None):
return fig;
def plotImage(self, xlim=None, sampling_rate=None):
if (sampling_rate is None):
sampling_rate = 30;
target_start = self.getTargetStart();
target_end = self.getTargetEnd() + 10;
target_duration = target_end - target_start;
new_n_samples = target_duration * sampling_rate;
target_start_times = np.linspace(target_start, target_end, num=new_n_samples, endpoint=True);
unwarped_target_times = [];
for st in target_start_times:
unwarped_target_times.append(self.warpTargetTime(st));
unwarped_target_times = np.array(unwarped_target_times);
pim = Image.PlotImage(signal=unwarped_target_times, show_axis=True, xvals=target_start_times,
sampling_rate=sampling_rate, events=self.target_events, xlime=[0, 100], ylims=[0, 110]);
return pim;
def repeatShorterEvents(self, endpoints=False):
n_events = max(len(self.source_events), len(self.target_events));
self.source_events = Event.RepeatToLength(self.source_events, n=n_events, endpoints=endpoints);
self.target_events = Event.RepeatToLength(self.target_events, n=n_events, endpoints=endpoints);
@staticmethod
def FromEvents(source_events, target_events):
w = Warp();
w.source_events = source_events;
w.target_events = target_events;
# w.repeatShorterEvents();
return w
@staticmethod
def LinearInterp(t, a_events, b_events):
n_events = min(len(a_events), len(b_events));
next_a_event_index = n_events;
for s in range(n_events):
if (t < a_events[s].start):
next_a_event_index = s;
break;
prev_a_event_time = 0;
prev_b_event_time = 0;
if (next_a_event_index > 0):
prev_a_event_time = a_events[next_a_event_index - 1].start;
prev_b_event_time = b_events[next_a_event_index - 1].start;
next_a_event_time = a_events[n_events - 1].start;
next_b_event_time = b_events[n_events - 1].start;
if (next_a_event_index < n_events):
next_a_event_time = a_events[next_a_event_index].start;
next_b_event_time = b_events[next_a_event_index].start;
a_event_gap = next_a_event_time - prev_a_event_time;
# b_event_gap = next_b_event_time - prev_b_event_time;
t_progress = t - prev_a_event_time;
# take care of past-the-end case, by simply letting time proceed normally past the last event
if (a_event_gap == 0):
return prev_b_event_time + t_progress;
next_weight = t_progress / (1.0 * a_event_gap);
return (next_weight * next_b_event_time) + ((1.0 - next_weight) * prev_b_event_time);
# additional_points = [];
# for i in range(-10, 11):
# additional_points.append([0.1 * i, 0.51])
@staticmethod
def plotWarpMethodTest(warp_type, additional_points=None, **kwargs):
sev = [];
tev = [];
pts = [[1.0, 1.0],
[-1.0, 1.0],
[0.5, 1.0],
[1.0, 0.5],
[-1.0, 0.5],
[0.5, 0.5],
[1.0, 0.3],
[-1.0, 0.3],
[0.5, 0.3]];
if (additional_points is not None):
pts = pts + additional_points;
currentt = [0.0, 0.0];
sev.append(Event(start=0.0));
tev.append(Event(start=0.0));
for p in pts:
currentt[0] = currentt[0] + p[0];
currentt[1] = currentt[1] + p[1];
sev.append(Event(start=currentt[0]));
tev.append(Event(start=currentt[1]));
# warp_type = 'target_time_source_fraction';
# other_params['acceleration_target_time'] = 0.5;
# other_params['acceleration_source_fraction'] = 0.75;
warpf = Warp.FromEvents(sev, tev);
warpf.setWarpFunc(warp_type, **kwargs);
warpf.plot()
@staticmethod
def SquareInterp(t, a_events, b_events):
n_events = min(len(a_events), len(b_events));
next_a_event_index = n_events;
for s in range(n_events):
if (t < a_events[s].start):
next_a_event_index = s;
break;
prev_a_event_time = 0;
prev_b_event_time = 0;
if (next_a_event_index > 0):
prev_a_event_time = a_events[next_a_event_index - 1].start;
prev_b_event_time = b_events[next_a_event_index - 1].start;
next_a_event_time = a_events[n_events - 1].start;
next_b_event_time = b_events[n_events - 1].start;
if (next_a_event_index < n_events):
next_a_event_time = a_events[next_a_event_index].start;
next_b_event_time = b_events[next_a_event_index].start;
a_event_gap = next_a_event_time - prev_a_event_time;
# b_event_gap = next_b_event_time - prev_b_event_time;
t_progress = t - prev_a_event_time;
# take care of past-the-end case, by simply letting time proceed normally past the last event
if (a_event_gap == 0):
return prev_b_event_time + t_progress;
progress_frac = t_progress / (1.0 * a_event_gap);
next_weight = math.pow(progress_frac, 2);
# accel = 3;
# bweight = math.pow(progress_frac,accel);
# aweight = math.pow(1.0-progress_frac,accel);
# sumweight = aweight+bweight;
# next_weight=bweight/sumweight;
return (next_weight * next_b_event_time) + ((1.0 - next_weight) * prev_b_event_time);
@staticmethod
def GetEventWarpFunc(from_events, to_events, f, lead_time=None, **kwargs):
start_cap_time = min(from_events[0].start, to_events[0].start);
if (lead_time is not None):
start_cap_time = min(start_cap_time, lead_time);
n_events = min(len(from_events), len(to_events));
# f_events = Event.GetUnrolledList(from_events[:n_events], assert_on_folds=True);
f_events = Event.GetUnrolledList(from_events[:n_events]);
t_events = Event.GetUnrolledList(to_events[:n_events]);
def rfunc(t, **kwargs):
next_f_event_index = n_events - 1;
for e in range(n_events):
if (t < f_events[e].unrolled_start):
next_f_event_index = e;
break;
if (next_f_event_index == 0):
from_cap_event = Event(start=f_events[0].start - start_cap_time, weight=0, type='startcap');
to_cap_event = Event(start=t_events[0].start - start_cap_time, weight=0, type='startcap')
return f(t, f_neighbors=[from_cap_event, f_events[0]], t_neighbors=[to_cap_event, t_events[0]]);
else:
return f(t,
f_neighbors=[f_events[next_f_event_index - 1], f_events[next_f_event_index]],
t_neighbors=[t_events[next_f_event_index - 1], t_events[next_f_event_index]]);
return rfunc;
@staticmethod
def WFunc_Quadratic():
def rfunc(t, f_neighbors, t_neighbors, **kwargs):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
next_weight = math.pow(progress_frac, 2);
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_Weight(use_to_weights=None, **kwargs):
print("USING WEIGHT-BASED WARP");
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
if (use_to_weights):
weight = t_neighbors[1].weight;
else:
weight = f_neighbors[1].weight;
p = 1.0 - weight;
# a = truediv(1.0, (1.0+p*p-2*p)); # if a=b
a = 1.0 - np.power((1.0 - p), 2.0); # b=1
if (progress_frac < p):
next_weight = a * progress_frac;
else:
next_weight = (a * progress_frac) + np.power((progress_frac - p), 2.0);
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_P(p=None, **kwargs):
if (p is None):
p = 0.5;
print(("USING P WARP with P={}".format(p)));
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
# a = truediv(1.0, (1.0+p*p-2*p)); # if a=b
a = 1.0 - np.power((1.0 - p), 2.0); # b=1
if (progress_frac < p):
next_weight = a * progress_frac;
else:
next_weight = (a * progress_frac) + np.power((progress_frac - p), 2.0);
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_Mouth(p_acceleration_time=0.1, **kwargs):
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
if (f_neighbors[1].type == 'mouth_open' or t_neighbors[1].type == 'mouth_open'):
p = 1.0 - truediv(p_acceleration_time, to_event_gap);
if (p < 0):
next_weight = math.pow(progress_frac, 2);
else:
# a = truediv(1.0, (1.0+p*p-2*p)); # if a=b
a = 1.0 - np.power((1.0 - p), 2.0); # b=1
if (progress_frac < p):
next_weight = a * progress_frac;
else:
next_weight = (a * progress_frac) + np.power((progress_frac - p), 2.0);
else:
next_weight = progress_frac;
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_targettime_sourcefraction(acceleration_target_time=0.1, acceleration_source_fraction=0.8, **kwargs):
"""
This assumes that you are mapping from the target to the source, as is the most common use case.
:param acceleration_target_time: amount of from time to spend accelerating
:param acceleration_source_fraction: fraction of source to accelerate through
:return:
"""
lin_source_fraction = 1.0 - acceleration_source_fraction;
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return to_times[
0] + t_progress; # is this right? doesnt seem to come up, not sure what behavior should be looking back on it...
progress_frac = truediv(t_progress, from_event_gap);
time_left = from_event_gap - t_progress;
p = 1.0 - truediv(acceleration_target_time, from_event_gap);
p2 = p * p;
q = 1.0 - acceleration_source_fraction;
if (acceleration_target_time >= from_event_gap or q > (p2)):
next_weight = math.pow(progress_frac, 2);
elif (time_left >= acceleration_target_time):
lin_t_progress_frac = truediv(t_progress, from_event_gap - acceleration_target_time);
next_weight = lin_t_progress_frac * lin_source_fraction;
else:
pdnom = (p2 - 2.0 * p + 1.0)
# I just used matlab to symbolic inverse matrix of equations, then simplified by hand
a = ((1.0 - q) / pdnom) + (q / (p * (p - 1)));
b = ((2 * p * (q - 1)) / pdnom) - ((q * (p + 1)) / (p2 - p))
# c = ((p2 - (q * (2 * p - 1))) / pdnom) + (q / (p - 1));
c = 1 - a - b;
next_weight = a * progress_frac * progress_frac + b * progress_frac + c;
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_target_source_fractions(acceleration_target_fraction=0.8, acceleration_source_fraction=0.9, **kwargs):
"""
This assumes that you are mapping from the target to the source, as is the most common use case.
:param acceleration_target_fraction: fraction of target to spend accelerating
:param acceleration_source_fraction: fraction of source to accelerate through
:return:
"""
lin_source_fraction = 1.0 - acceleration_source_fraction;
def rfunc(t, f_neighbors, t_neighbors):
print(acceleration_target_fraction)
print(acceleration_source_fraction)
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
to_event_gap = to_times[1] - to_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return to_times[
0] + t_progress; # is this right? doesnt seem to come up, not sure what behavior should be looking back on it...
progress_frac = truediv(t_progress, from_event_gap);
time_left = from_event_gap - t_progress;
p = 1.0 - acceleration_target_fraction;
p2 = p * p;
q = 1.0 - acceleration_source_fraction;
if (acceleration_target_fraction >= 1 or q > (p2)):
next_weight = math.pow(progress_frac, 2);
elif (progress_frac <= p):
lin_t_progress_frac = truediv(t_progress, p * from_event_gap);
next_weight = lin_t_progress_frac * lin_source_fraction;
else:
pdnom = (p2 - 2.0 * p + 1.0)
# I just used matlab to symbolic inverse matrix of equations, then simplified by hand
a = ((1.0 - q) / pdnom) + (q / (p * (p - 1)));
b = ((2 * p * (q - 1)) / pdnom) - ((q * (p + 1)) / (p2 - p))
# c = ((p2 - (q * (2 * p - 1))) / pdnom) + (q / (p - 1));
c = 1 - a - b;
next_weight = a * progress_frac * progress_frac + b * progress_frac + c;
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
return rfunc;
@staticmethod
def WFunc_AB(const_factor, quad_factor, **kwargs):
def rfunc(t, f_neighbors, t_neighbors):
from_times = Event.ToStartTimes(f_neighbors);
to_times = Event.ToStartTimes(t_neighbors);
from_event_gap = from_times[1] - from_times[0];
t_progress = t - from_times[0];
# avoid divide by 0
if (from_event_gap == 0):
AWARN("Event Gap was 0! Check Warp.py")
return prev_to_event_time + t_progress;
progress_frac = truediv(t_progress, from_event_gap);
next_weight = math.pow(progress_frac, 2);
return (next_weight * to_times[1]) + ((1.0 - next_weight) * to_times[0]);
@staticmethod
def ABWarp():
next_from_event_time = from_events[n_events - 1].start;
next_to_event_time = to_events[n_events - 1].start;
if (next_from_event_index < n_events):
next_from_event_time = from_events[next_from_event_index].start;
next_to_event_time = to_events[next_to_event_index].start;
from_event_gap = next_from_event_time - prev_from_event_time;
# b_event_gap = next_b_event_time - prev_b_event_time;
t_progress = t - prev_from_event_time;
# take care of past-the-end case, by simply letting time proceed normally past the last event
if (from_event_gap == 0):
return prev_to_event_time + t_progress;
progress_frac = t_progress / (1.0 * from_event_gap);
next_weight = math.pow(progress_frac, 2);
return (next_weight * next_to_event_time) + ((1.0 - next_weight) * prev_to_event_time);
@staticmethod
def CubicInterp(t, a_events, b_events):
# def CubicInterp(a_events, b_events, t):
f = Warp.CubicInterpFunc(a_events=a_events, b_events=b_events);
return f(t);
@staticmethod
def LinearInterpFunc(a_events, b_events):
if (a_events[0].start > 0):
ae = np.concatenate((np.asarray([0]), Event.ToStartTimes(a_events)));
else:
ae = Event.ToStartTimes(a_events);
be = Event.ToStartTimes(b_events);
if (len(be) > len(ae)):
be = be[:len(ae)];
elif (len(ae) > len(be)):
ae = ae[:len(be)];
return sp.interpolate.interp1d(ae, be, 'linear', bounds_error=False, fill_value='extrapolate');
@staticmethod
def CubicInterpFunc(a_events, b_events):
event_times = Event.ToStartTimes(a_events);
wevent_times = Event.ToStartTimes(b_events);
minlen = min(len(event_times), len(wevent_times));
event_times = event_times[:minlen];
wevent_times = wevent_times[:minlen];
splinecap = np.arange(0, 1, 0.25);
spline_times = np.concatenate((splinecap + event_times[0] - 1, event_times));
wspline_times = np.concatenate((splinecap + wevent_times[0] - 1, wevent_times));
spline_times = np.append(spline_times, splinecap + 0.5 + spline_times[-1]);
wspline_times = np.append(wspline_times, splinecap + 0.5 + wspline_times[-1]);
# get spline to translate initial times to warped times
splineX = sp.interpolate.interp1d(spline_times, wspline_times, kind='cubic', bounds_error=False,
fill_value='extrapolate');
return splineX;
================================================
FILE: src/video2npz/visbeat3/visbeat3/__init__.py
================================================
from .VisBeatImports import *
from .Video import *
from .VideoClip import *
from .VideoSource import *
from .VisBeatExampleVideo import VisBeatExampleVideo
import re
import os;
import shutil
from .SourceLocationParser import ParseSourseLocation
VISBEAT_ASSETS_DIR = './VisBeatAssets/';
from . import fileui
fileui.INITIAL_DIR = VISBEAT_ASSETS_DIR;
def SetAssetsDir(assets_dir):
global VISBEAT_ASSETS_DIR;
VISBEAT_ASSETS_DIR = assets_dir;
make_sure_dir_exists(assets_dir);
AINFORM("VISBEAT_ASSETS_DIR set to {}".format(VISBEAT_ASSETS_DIR));
make_sure_dir_exists(GetVideoSourcesDir());
temp_dir = os.path.join(VISBEAT_ASSETS_DIR, 'TEMP_FILES'+os.sep);
make_sure_dir_exists(temp_dir);
Video.VIDEO_TEMP_DIR = temp_dir;
fileui.INITIAL_DIR = VISBEAT_ASSETS_DIR;
def GetAssetsDir():
return VISBEAT_ASSETS_DIR;
def GetVideoSourcesDir():
video_sources_dir = os.path.join(GetAssetsDir(), 'VideoSources'+os.sep);
make_sure_dir_exists(video_sources_dir);
return video_sources_dir;
def PullVideo(name=None, source_location=None, max_height=240, **kwargs):
if(isinstance(name, VisBeatExampleVideo)):
assert(source_location is None), 'Provided VisBeatExampleVideo and source location? What are you trying to do?';
source_location = name.url;
vname = name.name;
elif(name is None):
assert(source_location is not None), "Must provide an argument to pullvideo";
sloc = ParseSourseLocation(source_location);
vname =sloc.code;
else:
vname = name;
vs = GetVideoSource(vname);
if(vs and vs.source_location==source_location):
v = vs.getVersion(max_height=max_height);
v.load(features_to_load = 'all');
return v;
print("destination:", GetVideoSourcesDir(), "name:", vname, "source_location:", source_location)
vs = VideoSource.NewVideoSource(destination=GetVideoSourcesDir(), name=vname, source_location=source_location, max_height=max_height, **kwargs);
v = vs.getVersion(max_height=max_height);
return v;
def ClipVideo(video, time_range, max_height=240):
video_fullres = video.source.getVersion();
vclip = video_fullres.VideoClip(start=time_range[0], end=time_range[1]);
vcdir = video.source.getDirForVersion(version_label='{}_{}'.format(str(time_range[0]), str(time_range[1])), version_group='Clips');
make_sure_dir_exists(vcdir);
vcname = video.getName() + 'clip_{}_{}'.format(str(time_range[0]), str(time_range[1]));
vcpath = os.path.join(vcdir, vcname+'.mp4');
vclip.write(output_path=vcpath);
vs = VideoSource.NewVideoSource(destination=GetVideoSourcesDir(), name=vcname, source_location=vcpath);
return vs.getVersion(max_height=max_height);
def GetVideoSource(name):
vname = name;
if (isinstance(name, VisBeatExampleVideo)):
vname = name.name;
path = os.path.join(GetVideoSourcesDir(), vname) + os.sep;
if (os.path.isdir(path)):
return VideoSource(path=path);
def LoadVideo(name, max_height=240):
vname = name;
if (isinstance(name, VisBeatExampleVideo)):
vname = name.name;
path = os.path.join(GetVideoSourcesDir(), vname)+os.sep;
if(os.path.isdir(path)):
vs = VideoSource(path=path);
v = vs.getVersion(max_height=max_height);
v.load(features_to_load = 'all');
return v;
else:
return None;
def Dancefer(source_video, target,
synch_video_beat=0, synch_audio_beat=0,
beat_offset = 0, leadin = None, nbeats=None,
source_harmonic = None, target_harmonic = None, source_harmonic_offset=None, target_harmonic_offset=None,
force_recompute=None, warp_type = 'quad',
name_tag=None, name_tag_prefix=None, output_path = None,
**kwargs):
"""
:param source_video: video to warp
:param target: music to warp to
:param synch_video_beat: integer specifying a beat (as in the nth beat) from the video to synchronize with synch_audio_beat
:param synch_audio_beat: integer specifying a beat (as in the nth beat) from the video to synchronize with synch_video_beat
:param beat_offset: Lets you offset which beats you want to render. This is mostly for testing different parts of an output.
:param leadin: how many beats before the synch beats to render
:param nbeats: lets you restrict output to rendering n beats
:param source_harmonic: can be None, 'half', or 'double'. 'half' will use every other beat, which you can offset with source_harmonic_offset. 'double' will add an additional beat between every consecutive beat. update - added 'third' for waltzes.
:param target_harmonic: can be None, 'half', or 'double'. 'half' will use every other beat, which you can offset with source_harmonic_offset. 'double' will add an additional beat between every consecutive beat. update - added 'third' for waltzes.
:param source_harmonic_offset: optional offset for harmonic
:param target_harmonic_offset: optional offset for harmonic
:param force_recompute:
:param warp_type:
:param name_tag:
:param name_tag_prefix:
:param output_path:
:param kwargs:
:return:
"""
if((output_path is not None) and (not force_recompute)):
if(os.path.exists(output_path)):
return Video(output_path);
if(isinstance(target, Video)):
target_audio = target.getAudio();
else:
target_audio = target;
synchaudio = synch_audio_beat;
synchvideo = synch_video_beat;
lead_in = leadin;
if(lead_in is None):
lead_in = min(synchaudio, synchvideo);
elif(isinstance(lead_in, str) and lead_in[0]=='<'):
# lead_in = min(synchaudio, synchvideo, int(lead_in));
lead_in = min(synchaudio, int(lead_in));
start_audio_beat = synchaudio-lead_in;
start_video_beat = synchvideo-lead_in;
if(beat_offset and beat_offset>0):
start_audio_beat = start_audio_beat+beat_offset;
start_video_beat = start_video_beat+beat_offset;
print(("Warping {} to {}".format(source_video.getName(), target_audio.getName())));
bitrate = None;
vbeats = source_video.audio.getBeatEvents()
tbeats = target_audio.getBeatEvents()
if(start_video_beat < 0):
if(synchvideo == 0):
vbeats = [vbeats[0].clone()]+vbeats;
vbeats[0].start = vbeats[0].start-(vbeats[2].start-vbeats[1].start);
vbadd = Event.SubdivideIntervals(vbeats[:2], -start_video_beat);
vbeats = vbadd+vbeats[2:];
start_video_beat = 0;
vbeats = vbeats[start_video_beat:];
tbeats = tbeats[start_audio_beat:];
if(source_harmonic=='half'):
vbeats = Event.Half(vbeats, source_harmonic_offset);
elif (source_harmonic == 'third'):
vbeats = Event.Third(vbeats, source_harmonic_offset);
elif(source_harmonic == 'double'):
vbeats = Event.Double(vbeats);
if (target_harmonic == 'half'):
tbeats = Event.Half(tbeats, target_harmonic_offset);
elif (target_harmonic == 'third'):
tbeats = Event.Third(tbeats, target_harmonic_offset);
elif (target_harmonic == 'double'):
tbeats = Event.Double(tbeats);
if(nbeats):
print(("Rendering {} beats of result".format(nbeats)))
if(len(vbeats)>nbeats):
vbeats = vbeats[:nbeats];
print((len(vbeats)))
if(len(tbeats)>nbeats):
tbeats = tbeats[:nbeats];
print((len(tbeats)))
else:
if(vbeats[-1].start0):
start_audio_beat = start_audio_beat+beat_offset;
start_video_beat = start_video_beat+beat_offset;
print(("Warping {} to {}".format(source_video.getName(), target_audio.getName())));
bitrate = None;
vbeats = source_beats;
if(source_beats is None):
vbeats = source_video.getVisualBeats();
tbeats = target_beats;
if(target_beats is None):
tbeats = target_audio.getBeatEvents();
if(start_video_beat < 0):
if(synchvideo == 0):
vbeats = [vbeats[0].clone()]+vbeats;
vbeats[0].start = vbeats[0].start-(vbeats[2].start-vbeats[1].start);
vbadd = Event.SubdivideIntervals(vbeats[:2], -start_video_beat);
vbeats = vbadd+vbeats[2:];
start_video_beat = 0;
vbeats = vbeats[start_video_beat:];
tbeats = tbeats[start_audio_beat:];
if (source_harmonic == 'half'):
vbeats = Event.Half(vbeats, source_harmonic_offset);
elif (source_harmonic == 'third'):
vbeats = Event.Third(vbeats, source_harmonic_offset);
elif (source_harmonic == 'double'):
vbeats = Event.Double(vbeats);
if (target_harmonic == 'half'):
tbeats = Event.Half(tbeats, target_harmonic_offset);
elif (target_harmonic == 'third'):
tbeats = Event.Third(tbeats, target_harmonic_offset);
elif (target_harmonic == 'double'):
tbeats = Event.Double(tbeats);
if(nbeats):
print(("Rendering {} beats of result".format(nbeats)))
if(len(vbeats)>nbeats):
vbeats = vbeats[:nbeats];
print((len(vbeats)))
if(unfold_to_n):
vbeats = Event.UnfoldToN(vbeats, unfold_to_n, momentum=momentum);
if (len(tbeats) > len(vbeats)):
tbeats = tbeats[:len(vbeats)];
if(warp_type is 'weight'):
vbeats = source_video.visualBeatsFromEvents(vbeats);
if(name_tag is None):
name_tag = warp_type+'_sab_'+str(start_audio_beat)+'_svb_'+str(start_video_beat);
if(name_tag_prefix is not None):
name_tag = name_tag+name_tag_prefix;
warp_args = dict(target=target_audio,
source_events=vbeats,
target_events = tbeats,
warp_type=warp_type,
force_recompute=force_recompute,
name_tag = name_tag)
if(bitrate):
warp_args.update(dict(bitrate=bitrate));
warp_args.update(kwargs);
warped_result = source_video.getWarped(**warp_args);
if(output_path):
final_output_path = output_path;
if(os.path.isfile(final_output_path)):
output_filename = os.path.basename(output_path);
name_parts = os.path.splitext(output_filename);
output_filename_base = name_parts[0];
output_directory_path = os.path.dirname(output_path);
if (output_directory_path == ''):
output_directory_path = '.'
output_ext = name_parts[1];
ntry = 1;
tryname = output_filename_base+ '_' + str(ntry);
while (os.path.isfile(os.path.join(output_directory_path, tryname+output_ext)) and ntry<100):
ntry = ntry+1;
tryname = output_filename_base + '_' + str(ntry);
final_output_path = os.path.join(output_directory_path, tryname + output_ext);
shutil.copy2(src=warped_result.getPath(), dst=final_output_path);
n_frames_total = warped_result.num_frames_total;
warp_used = warped_result.getInfo('warp_used');
warped_result_final = Video(path = final_output_path, num_frames_total=n_frames_total);
warped_result_final.setInfo(label='warp_used', value=warp_used);
os.remove(warped_result.getPath())
warped_result = warped_result_final;
return warped_result;
def getVBSegments(self,source_video,
source_beats = None,
search_tempo=None,
search_window=None,
max_height=None,
beat_limit=None,
n_return=None,
unary_weight=None,
binary_weight=None,
break_on_cuts=None,
peak_vars=None):
source = source_video;
if(source_beats is None):
if (peak_vars is not None):
vbeats = source.getFeature('simple_visual_beats', **peak_vars);
else:
vbeats = source.getFeature('simple_visual_beats');
else:
vbeats = source_beats;
#
if (search_tempo is not None):
tempo = search_tempo;
beat_time = np.true_divide(60.0, tempo);
clips = VisualBeat.PullOptimalPaths_Basic(vbeats, target_period=beat_time, unary_weight=unary_weight,
binary_weight=binary_weight, break_on_cuts=break_on_cuts,
window_size=search_window);
else:
clips = VisualBeat.PullOptimalPaths_Autocor(vbeats, unary_weight=unary_weight, binary_weight=binary_weight,
break_on_cuts=break_on_cuts, window_size=search_window);
if (beat_limit is None):
beat_limit = 2;
print(("There were {} candidates".format(len(vbeats))));
nclips = 0;
segments = [];
for S in clips:
if (len(S) > beat_limit):
nclips = nclips + 1;
segments.append(S);
if (n_return is not None):
segments.sort(key=len, reverse=True);
segments = segments[:n_return];
return segments;
================================================
FILE: src/video2npz/visbeat3/visbeat3/_dancefer_examples.py
================================================
from .VisBeatExampleVideo import *
from ._music_examples import *
# dances = [];
dances.append(VisBeatExampleVideo(display_name = 'SNSD: HAHAHA', name='snsd_hahaha', url='https://www.youtube.com/watch?v=OxNsx0eMsGU', start_beat=42));
dances.append(VisBeatExampleVideo(display_name = 'Boston Dynamics: Spot the Dancing Robot', name='spot_the_dancing_robot', url='https://www.youtube.com/watch?v=kHBcVlqpvZ8', start_beat = 9));
dances.append(VisBeatExampleVideo(display_name = 'Michael Jackson: Thriller', name = 'thriller', url = 'https://www.youtube.com/watch?v=wlHUJbl-t7o', start_beat = 4))
dances.append(VisBeatExampleVideo(display_name = 'LMFAO: Party Rock Anthem',name='party_rock', url='https://www.youtube.com/watch?v=WZRMpC_wh0M', start_beat=4, leadin=4))
dances.append(VisBeatExampleVideo(display_name = 'BTS: Boy in Luv', name='boy_in_luv', url='https://www.youtube.com/watch?v=gqz6Adx63w8', start_beat=34));
dances.append(VisBeatExampleVideo(display_name = 'Thays Monaro: Redneck Woman',name='gwilson_redneck_woman', url='https://www.youtube.com/watch?v=1apy8YPygKo', start_beat=65))
dances.append(VisBeatExampleVideo(display_name = 'Music Express: Dancing in the Street', name='dance_cc_dancing_in_the_street', url='https://www.youtube.com/watch?v=fzZ2CoL3IMQ', start_beat=3));
dances.append(VisBeatExampleVideo(display_name = 'Barney and Friends: Mr. Golden Sun',name='barney_mr_golden_sun', url='https://www.youtube.com/watch?v=ya4yyg9XiI4', start_beat=24))
dances.append(VisBeatExampleVideo(display_name = 'M. Express: Friends Forever', name='dance_cc_friends_forever', url='https://www.youtube.com/watch?v=T6ZX6wkJ5Ns', start_beat=2));
dances.append(VisBeatExampleVideo(display_name = 'Just Dance Kids: Gummy Bear',name='jdk_gummy_bear', url='https://www.youtube.com/watch?v=KVE-T2_vLpY', start_beat=60))
dances.append(VisBeatExampleVideo(display_name = 'M. Express: Feelin Good',name='dance_cc_feelin_good', url='https://www.youtube.com/watch?v=uBWp9rr6w08', start_beat=49));
# dances.append(VisBeatExampleVideo(display_name = 'Kiesza: Hideaway', name='hideaway', url='https://www.youtube.com/watch?v=Vnoz5uBEWOA', start_beat=124))
dances.append(VisBeatExampleVideo(display_name = 'SNSD: Genie', name='snsd_genie', url='https://www.youtube.com/watch?v=6SwiSpudKWI', start_beat=141));
dances.append(VisBeatExampleVideo(display_name = 'Momoland Boom Boom', name='momoland_boom_boom', url='https://www.youtube.com/watch?v=0HKfjsM2hSw', start_beat = 145));#33#
dances.append(VisBeatExampleVideo(display_name = 'Snap: Rhythm is a Dancer', name='rhythm_is_a_dancer', url='https://www.youtube.com/watch?v=fDWFVI8PQOI', start_beat=65));
dances.append(VisBeatExampleVideo(display_name = 'Janet Jackson: Rhythm Nation', name='rhythm_nation', url='https://www.youtube.com/watch?v=OAwaNWGLM0c', start_beat = 226));
dances.append(VisBeatExampleVideo(display_name = 'BTS Just One Day', name='bts_just_one_day', url='https://www.youtube.com/watch?v=KQeAg45p2UI', start_beat=200));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
# dances.append(VisBeatExampleVideo(display_name = '', name='', url='', start_beat = ));
================================================
FILE: src/video2npz/visbeat3/visbeat3/_dancify_examples.py
================================================
from .VisBeatExampleVideo import *
from ._music_examples import *
dances.append(VisBeatExampleVideo(display_name = 'Turtle', name='turtle', url='https://www.youtube.com/watch?v=PWD4gktEUAY', start_beat=0));
dances.append(VisBeatExampleVideo(display_name = 'Louie The Cat', name='louie_the_cat', url='https://www.youtube.com/watch?v=hqFG6d86ygI', start_beat=None));
accidental_dances = [];
accidental_dances.append(VisBeatExampleVideo(display_name="Trump IACP Full", name="trump_iacp_full", url='https://www.youtube.com/watch?v=pu4dPTi6SEg', target_n_beats = 7))
accidental_dances.append(VisBeatExampleVideo(display_name="Trump Tax Reform WH.gov Full", name="trump_taxreform_remarks_1", url="https://www.youtube.com/watch?v=zB-lhTEQdKY"))
# accidental_dances.append(VisBeatExampleVideo(display_name="", name="", url=""))
synth = [];
synth.append(VisBeatExampleVideo(name='synth_ball_metronome_w_noise', url = 'https://youtu.be/-mqJIGdro6A', start_beat = None));
synth.append(VisBeatExampleVideo(name='synth_test_ball_1', url = 'https://youtu.be/SjXsMYBJEF8', start_beat = None));
synth.append(VisBeatExampleVideo(name='synth_test_ball_1_gt_impact_sounds', url = 'https://youtu.be/tsdsQm4iTNg', start_beat = None));
================================================
FILE: src/video2npz/visbeat3/visbeat3/_mediafiles.py
================================================
import os
VB_MEDIA_UTILS_PATH = os.path.abspath(__file__)
VB_MEDIA_UTILS_DIR = os.path.abspath(os.path.dirname(__file__));
MEDIAFILES_DIR = os.path.join(VB_MEDIA_UTILS_DIR, 'assets'+os.sep)
AUDIO_FILES_DIR = os.path.join(MEDIAFILES_DIR, 'audio'+os.sep);
AUDIO_FILES = [];
AUDIO_FILE_PATHS = {};
for filename in os.listdir(AUDIO_FILES_DIR):
# if(reduce(lambda x,y: x or y, map(lambda ext: filename.lower().endswith(ext), Audio.MEDIA_FILE_EXTENSIONS()))):
AUDIO_FILES.append(filename);
AUDIO_FILE_PATHS[filename]=(os.path.join(AUDIO_FILES_DIR, filename));
def GetTestAudioPath(filename):
return AUDIO_FILE_PATHS[filename];
VIDEO_FILES_DIR = os.path.join(MEDIAFILES_DIR, 'video'+os.sep);
VIDEO_FILES = [];
VIDEO_FILE_PATHS = [];
if(os.path.exists(VIDEO_FILES_DIR)):
for filename in os.listdir(VIDEO_FILES_DIR):
VIDEO_FILES.append(filename);
VIDEO_FILE_PATHS.append(os.path.join(VIDEO_FILES_DIR, filename));
IMAGE_FILES_DIR = os.path.join(MEDIAFILES_DIR, 'images'+os.sep);
IMAGE_FILES = [];
IMAGE_FILE_PATHS = {};
for filename in os.listdir(IMAGE_FILES_DIR):
IMAGE_FILES.append(filename);
IMAGE_FILE_PATHS[filename] = (os.path.join(IMAGE_FILES_DIR, filename));
def GetTestImagePath(filename=None):
if(filename is None):
filename = "VisBeatWatermark.png"
return IMAGE_FILE_PATHS[filename];
def GetVBMarkPath():
return IMAGE_FILE_PATHS["VisBeatWatermark.png"];
================================================
FILE: src/video2npz/visbeat3/visbeat3/_music_examples.py
================================================
from .VisBeatExampleVideo import *
dances = [];
music = [];
music.append(VisBeatExampleVideo(display_name = 'U Cant Touch This', name='cant_touch_this', url='https://www.youtube.com/watch?v=_NNYI8VbFyY', start_beat=2, leadin=2));
music.append(VisBeatExampleVideo(display_name = 'Mary Poppins: Supercalifrag.', name='supercalifrag', url='https://www.youtube.com/watch?v=rihNRTTcztQ', start_beat = 5, leadin = 3));
music.append(VisBeatExampleVideo(display_name = 'Migos: Walk It Talk It',name='walkit_talkit', url='https://www.youtube.com/watch?v=fGqdIPer-ms', start_beat = 134));
music.append(VisBeatExampleVideo(display_name = 'Rammstein: Du Hast',name='du_hast', url = 'https://www.youtube.com/watch?v=W3q8Od5qJio', start_beat = 193));
music.append(VisBeatExampleVideo(display_name = 'Taylor Swift: Shake It Off', name='shake_it_off', url='https://www.youtube.com/watch?v=nfWlot6h_JM', start_beat=112));
music.append(VisBeatExampleVideo(display_name = 'Michael Jackson: Billie Jean', name='billie_jean', url='https://www.youtube.com/watch?v=Zi_XLOBDo_Y', start_beat=169));
music.append(VisBeatExampleVideo(display_name = 'Hall and Oates: You Make My Dreams', name='you_make_my_dreams', url='https://www.youtube.com/watch?v=EErSKhC0CZs', start_beat=95));
music.append(VisBeatExampleVideo(display_name = 'Parry Gripp: Breakfast Burrito',name="breakfast_burrito", url='https://www.youtube.com/watch?v=prPjpwsGiws', start_beat=32))
music.append(VisBeatExampleVideo(display_name = 'Pharrell Williams: Happy',name='happy', url='https://www.youtube.com/watch?v=y6Sxv-sUYtM', start_beat=69, leadin=3))
music.append(VisBeatExampleVideo(display_name = 'Aqua: Barbie Girl',name='barbie_girl', url='https://www.youtube.com/watch?v=ZyhrYis509A', start_beat=67, leadin=4));
music.append(VisBeatExampleVideo(display_name = 'Jhameel: Montage',name='music_cc_jhameel_montage', url='https://www.youtube.com/watch?v=vYr_nCmsgoE', start_beat=103))
music.append(VisBeatExampleVideo(display_name = 'Vengaboys: We like to Party',name='we_like_to_party', url='https://www.youtube.com/watch?v=6Zbi0XmGtMw', start_beat=65))
music.append(VisBeatExampleVideo(display_name = 'Rick Astley: Never Gonna Give You Up', name='rick_roll', url='https://www.youtube.com/watch?v=dQw4w9WgXcQ', start_beat = 3, leadin=3));
music.append(VisBeatExampleVideo(display_name = 'Mark Ronson: Uptown Funk ft. Bruno Mars', name='uptown_funk', url='https://www.youtube.com/watch?v=OPf0YbXqDm0', start_beat=32));
music.append(VisBeatExampleVideo(display_name = 'Missy Elliot: Work It', name='work_it', url='https://www.youtube.com/watch?v=cjIvu7e6Wq8', start_beat=52, leadin = 1));
music.append(VisBeatExampleVideo(display_name = 'If I only had a brain', name='only_had_a_brain', url='https://www.youtube.com/watch?v=nauLgZISozs', start_beat=14));
music.append(VisBeatExampleVideo(display_name = 'Kane Brown: Lose It', name='kb_lose_it', url='https://www.youtube.com/watch?v=Z8nkc2KKjd8', start_beat=56));
# music.append(VisBeatExampleVideo(display_name = 'Check Meowt', name='pg_check_meowt', url='https://youtu.be/NjKYX4bQpf0', start_beat = 16));
# music.append(VisBeatExampleVideo(display_name = 'Wu-Tang Clan: Protect Ya Neck', name='wutang_protect_ya_neck', url='https://www.youtube.com/watch?v=R0IUR4gkPIE', start_beat = None));
# music.append(VisBeatExampleVideo(display_name = 'Ice Cube: It Was A Good Day',name='it_was_a_good_day', url='https://www.youtube.com/watch?v=h4UqMyldS7Q', start_beat=64, harmonic = 'half'));
================================================
FILE: src/video2npz/visbeat3/visbeat3/command_line.py
================================================
================================================
FILE: src/video2npz/visbeat3/visbeat3/fileui/__init__.py
================================================
from sys import platform
if platform == "linux" or platform == "linux2":
PLATFORM = 'linux';
elif platform == "darwin":
PLATFORM = 'osx';
elif platform == "win32":
PLATFORM = 'windows'
SUPPORTED = False;
INITIAL_DIR ='./';
if(PLATFORM == 'osx'):
from . import uipath
def GetFilePath(initial_path=None):
if(initial_path is None):
return uipath.uiGetFilePath(initial_path=INITIAL_DIR);
else:
return uipath.uiGetFilePath(initial_path);
def GetDirectory(initial_path=None):
if(initial_path is None):
return uipath.uiGetDirectory(initial_path=INITIAL_DIR);
else:
return uipath.uiGetDirectory(initial_path);
def GetSaveFilePath(initial_path=None, file_extension = None):
if(initial_path is None):
return uipath.uiGetSaveFilePath(initial_path=INITIAL_DIR, file_extension=file_extension);
else:
return uipath.uiGetSaveFilePath(initial_path=initial_path, file_extension=file_extension);
def Show(path):
uipath.showInFinder(path);
def Open(path):
uipath.openOSX(path);
SUPPORTED = True;
else:
def GetFilePath(initial_path=None):
return None;
def GetDirectory(initial_path=None):
return None;
def GetSaveFilePath(initial_path=None, file_extension = None):
return None;
def Show(path):
return None;
def Open(path):
return None;
================================================
FILE: src/video2npz/visbeat3/visbeat3/fileui/uipath.py
================================================
import os
import subprocess
def uiGetFilePath(initial_path=None):
try:
if(initial_path):
output = subprocess.check_output("osascript -e 'set strPath to POSIX file \"{}\"' -e 'set theDocument to choose file with prompt \"Please select a document to process:\" default location strPath' -e 'set theDocument to (the POSIX path of theDocument)'".format(initial_path), shell=True)
else:
output = subprocess.check_output("osascript -e 'set theDocument to choose file with prompt \"Please select a document to process:\"' -e 'set theDocument to (the POSIX path of theDocument)'", shell=True)
return output.replace('\n', '');
except subprocess.CalledProcessError as e:
print((e.output));
# assert(False)
# grabpath = get_ipython().run_cell_magic(u'bash', u'', "osascript -e 'set theDocument to choose file with prompt \"Please select a document to process:\"' -e 'set theDocument to (the POSIX path of theDocument)'>&2")
def uiGetDirectory(initial_path=None):
try:
if(initial_path):
output = subprocess.check_output("osascript -e 'set strPath to POSIX file \"{}\"' -e 'set thedir to choose folder with prompt \"Please select a file:\" default location strPath' -e 'set thedir to (the POSIX path of thedir)'".format(initial_path), shell=True)
else:
output = subprocess.check_output("osascript -e 'set thedir to choose folder with prompt \"Please select a directory:\"' -e 'set thedir to (the POSIX path of thedir)'", shell=True)
return output.replace('\n', '');
except subprocess.CalledProcessError as e:
print((e.output));
# assert(False)
def uiGetSaveFilePath(initial_path=None, file_extension=None):
try:
osastr = "osascript ";
if(initial_path):
osastr = osastr+"-e 'set strPath to POSIX file \"{}\"' ".format(initial_path);
osastr = osastr+"-e 'set theDocument to choose file name with prompt \"Save As File:\" ";
if(initial_path):
osastr = osastr+"default location strPath";
osastr = osastr+"' ";
osastr = osastr+"-e 'set theDocument to (the POSIX path of theDocument)'"
output = subprocess.check_output(osastr, shell=True);
ostring = output.replace('\n', '');
if (file_extension is not None):
if (not ostring.endswith(file_extension)):
ostring = ostring + file_extension;
return ostring;
except subprocess.CalledProcessError as e:
AWARN('ERROR')
print((e.output));
def showInFinder(path):
return openOSX(get_dir_from_path(path));
def openOSX(path):
return subprocess.check_output("open {}".format(put_string_in_quotes(path)), shell=True);
def put_string_in_quotes(s):
return "\""+s+"\""
def get_file_name_from_path(pth):
return os.path.split(pth)[1];
def get_dir_from_path(pth):
return (os.path.split(pth)[0]+os.sep);
================================================
FILE: src/video2npz/visbeat3/visbeat3/vbgui/BeatGUI.py
================================================
from visbeat3.AImports import *
VIEWER_INSTALLED = 1;
try:
import vbwidget as Viewer
except ImportError as e:
VIEWER_INSTALLED = 0;
AWARN("VBViewer not installed. Consider installing for full functionality.")
from ..TimeSignal import *
from ..EventList import *
#this is what media should call to get its gui object
def media_GUI_func(self):
if (self._gui is None):
self._gui = BeatGUI();
self._gui.media = self;
return self._gui;
class BeatGUI(AObject):
"""
"""
def AOBJECT_TYPE(self):
return 'BeatGUI';
def __init__(self, media=None, path=None, clear_temp=None):
"""If you provide a directory, it will look for a existing AFileManager.json in that directory, or create one if it does not already exist.
If you provide a json, it will use that json, unless the json doesn't exist, in which case it will complain...
"""
AObject.__init__(self, path=path);
if(media is not None):
self.media = media;
def initializeBlank(self):
AObject.initializeBlank(self);
self._widget = None;
self._media = None;
def getJSONName(self):
return self.AOBJECT_TYPE()+".json";
#########
#
@property
def media(self):
return self._getMedia();
def _getMedia(self):
return self._media;
@media.setter
def media(self, value):
self._setMedia(value);
def _setMedia(self, value):
self._media = value;
#
#
@property
def media_type(self):
return self._getMediaType();
def _getMediaType(self):
if(self.media is None):
return None;
else:
return self.media.AObjectType();
#
#
@property
def widget(self):
return self._getWidget();
def _getWidget(self):
if (self._widget is None):
self._widget = Viewer.VBVSignal();
return self._widget;
@widget.setter
def widget(self, value):
self._setWidget(value);
def _setWidget(self, value):
self._widget = value;
#
#
@property
def frame_rate(self):
return self._getFrameRate();
def _getFrameRate(self):
gfr = self.widget.frame_rate;
if (gfr is None):
media = self.media;
if (media is not None):
gfr = media.getFrameRate();
return gfr;
@frame_rate.setter
def frame_rate(self, value):
self._setFrameRate(value);
def _setFrameRate(self, value):
self.widget.frame_rate = float(value);
#
#
@property
def frame_offset(self):
return self._getFrameOffset();
def _getFrameOffset(self):
return self.widget.frame_offset;
@frame_offset.setter
def frame_offset(self, value):
self._setFrameOffset(value);
def _setFrameOffset(self, value):
self.widget.frame_offset = value;
#
def run(self, local_saliency=None, frame_rate = None, eventlist = 'default', frame_offset=None):
if(frame_rate is None):
# self.widget.frame_rate = float(self.getMedia().getFrameRate());
self.frame_rate = self.media._getFrameRate();
else:
# self.widget.frame_rate = float(frame_rate);
self.frame_rate = frame_rate;
if(local_saliency is None):
self.widget.signal = self.media.getLocalRhythmicSaliency().tolist();
# self.widget.signal = self.getBothWayVisualImpactEnvelope(highpass_window_seconds=None, force_recompute = True).tolist();
else:
self.widget.signal = local_saliency.tolist();
if(frame_offset is None):
self.frame_offset = 0;
elif(frame_offset is 'guess'):
self.frame_offset = self.guessFrameOffset();
else:
self.frame_offset = frame_offset;
if(eventlist is None):
self.widget.events = [];
elif(eventlist == 'default'):
self.widget.events = EventList._toGUIDicts(self.media.getEventList());
else:
self.widget.events = EventList._toGUIDicts(eventlist);
self.widget.data_string = self.media.getStringForHTMLStreamingBase64();
return self.widget;
def guessFrameOffset(self):
if(isinstance(self.media, Video)):
return self.media.reader.get_length() - self.media.n_frames();
else:
return 0;
def deactivateAllEvents(self):
newes = []
gevents = self.getEventDicts();
for e in gevents:
newe = e;
newe['is_active']=0;
newes.append(newe);
self.widget.events = [];
self.widget.events = newes;
def activateAllEvents(self):
newes = []
gevents = self.getEventDicts();
for e in gevents:
newe = e;
newe['is_active'] = 1;
newes.append(newe);
self.widget.events = [];
self.widget.events = newes;
def activatePattern(self, pattern=None, prefix=None, apply_to_active=None):
assert(pattern), "must provide pattern to activate"
newes = []
gevents = self.getGUIEventDicts();
counter = 0;
prefix_length = 0;
if(prefix_length is not None):
prefix_length = len(prefix);
for i, e in enumerate(gevents):
if (apply_to_active):
if (e.get('is_active')):
if (counter < prefix_length):
e['is_active']=prefix[counter];
else:
e['is_active'] = pattern[(counter - prefix_length) % len(pattern)];
counter = counter + 1;
else:
print(("Skipping beat {}, inactive".format(i)));
else:
if (i < prefix_length):
e['is_active'] = prefix[i];
else:
e['is_active'] = pattern[(i - prefix_length) % len(pattern)];
newes.append(e);
self.widget.events = [];
self.widget.events = newes;
def shiftEventsByNFrames(self, n_frames=None):
assert(n_frames), "must provide number of frames to shift by"
newes = []
gevents = self.getEventDicts();
sample_step = np.true_divide(1.0,self.getFrameRate());
for e in gevents:
newe = e;
newe['start'] = newe['start']+n_frames*sample_step;
newes.append(newe);
self.widget.events = [];
self.widget.events = newes;
def getActiveEventTimes(self):
gevents = self.getEventDicts(active_only=True);
revents = []
for e in gevents:
revents.append(e.get('time'));
return np.asarray(revents);
def getEventTimes(self):
gevents = self.getEventDicts();
revents = []
for e in gevents:
revents.append(e.t);
return np.asarray(revents);
def getEvents(self, active_only=None):
return Event._FromGUIDicts(self.getEventDicts(active_only = active_only));
def getEventList(self, active_only=None):
elist = EventList._FromGUIDicts(self.getEventDicts(active_only=active_only));
elist.setInfo(label='html_frame_offset', value=self.getFrameOffset());
return elist;
def getActiveEvents(self):
return self.getEvents(active_only=True);
def getEventDicts(self, active_only = None):
gevents = self.widget.events[:];
if(not active_only):
return gevents;
else:
nevents = []
for e in gevents:
if(e.get('is_active')):
nevents.append(e);
return nevents;
def saveEvents(self, save_path = None):
elist = self.getEventList(active_only=False);
if(save_path is not None):
elist.writeToJSON(json_path=save_path);
self.widget.last_save_path = save_path;
else:
save_path = self.widget.last_save_path;
if(save_path is None):
save_path = uiGetSaveFilePath(file_extension='.json');
if(save_path is not None):
elist.writeToJSON(json_path=save_path);
self.widget.last_save_path = save_path;
def saveEventsAs(self, save_path = None):
elist = self.getEventList(active_only=False);
if (save_path is not None):
elist.writeToJSON(json_path=save_path);
self.widget.last_save_path = save_path;
print(('savepath not none {}'.format(save_path)))
else:
save_path = uiGetSaveFilePath(file_extension='.json');
print(('savepath from ui {}'.format(save_path)))
if (save_path is not None):
print(('save path from ui {}'.format(save_path)));
elist.writeToJSON(json_path=save_path);
self.widget.last_save_path = save_path;
print(save_path)
def setEvents(self, events):
self.widget.events = Event._ToGUIDicts(events);
def setEventList(self, event_list):
if(event_list.getInfo('html_frame_offset') is not None):
self.widget.frame_offset = event_list.getInfo('html_frame_offset');
self.widget.events = event_list._toGUIDicts();
def loadEvents(self, load_path = None):
if(load_path is None):
load_path = uiGetFilePath();
elist = EventList();
elist.loadFromJSON(json_path=load_path);
self.setEventList(event_list = elist);
def getEventListWithSelectedSegments(self):
eventlist = self.getEventList();
events = eventlist.events;
segments = [];
for i, e in enumerate(events):
if(e.direction>-1): # meaning not a back beat
newseg = [];
for si in range(i, len(events)):
newseg.append(si);
if(events[si].direction<0): # meaning a back beat
break;
segments.append(newseg);
eventlist.setInfo(label='selected_segments', value=segments);
return eventlist;
================================================
FILE: src/video2npz/visbeat3/visbeat3/vbgui/__init__.py
================================================
================================================
FILE: src/video2npz/visbeat3/visbeat3.egg-info/PKG-INFO
================================================
Metadata-Version: 2.1
Name: visbeat3
Version: 0.0.8
Summary: Python3 Implementation for 'Visual Rhythm and Beat' SIGGRAPH 2018
Home-page: https://github.com/haofanwang/visbeat3
Author: Haofan Wang
Author-email: haofanwang.ai@gmail.com
License: UNKNOWN
Description: # visbeat3
This is a migration of [visbeat](http://abedavis.com/visualbeat/) from Python2 to Python3. All credits belong to the original author.
Note: This repo is under development, for any issue, please PR directly!
## Install
```
pip3 install visbeat3
```
or
```
pip3 install -e git+https://github.com/haofanwang/visbeat3.git#egg=visbeat3
```
## Usage
```
import visbeat3 as vb
```
## Reference
```
@inproceedings{davis2018visual,
title={Visual rhythm and beat},
author={Davis, Abe and Agrawala, Maneesh},
booktitle={Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition Workshops},
pages={2532--2535},
year={2018}
}
```
Platform: UNKNOWN
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Description-Content-Type: text/markdown
================================================
FILE: src/video2npz/visbeat3/visbeat3.egg-info/SOURCES.txt
================================================
.DS_Store
LICENSE
LICENSE.pdf
MANIFEST.in
README.md
setup.cfg
setup.py
test.py
.git/.DS_Store
.git/HEAD
.git/config
.git/description
.git/index
.git/packed-refs
.git/hooks/applypatch-msg.sample
.git/hooks/commit-msg.sample
.git/hooks/fsmonitor-watchman.sample
.git/hooks/post-update.sample
.git/hooks/pre-applypatch.sample
.git/hooks/pre-commit.sample
.git/hooks/pre-merge-commit.sample
.git/hooks/pre-push.sample
.git/hooks/pre-rebase.sample
.git/hooks/pre-receive.sample
.git/hooks/prepare-commit-msg.sample
.git/hooks/push-to-checkout.sample
.git/hooks/update.sample
.git/info/exclude
.git/logs/HEAD
.git/logs/refs/heads/main
.git/logs/refs/remotes/origin/HEAD
.git/objects/pack/pack-390cb819f9aa179975f055403fc70bc5f8d17684.idx
.git/objects/pack/pack-390cb819f9aa179975f055403fc70bc5f8d17684.pack
.git/refs/heads/main
.git/refs/remotes/origin/HEAD
VisBeatAssets/.DS_Store
VisBeatAssets/VideoSources/.DS_Store/VideoSource.json
VisBeatAssets/VideoSources/.DS_Store/Versions/Source/Full/.DS_Store
VisBeatAssets/VideoSources/animation.mp4/.DS_Store
VisBeatAssets/VideoSources/animation.mp4/VideoSource.json
VisBeatAssets/VideoSources/animation.mp4/Data/.DS_Store
VisBeatAssets/VideoSources/animation.mp4/Data/Backups/VideoSource.json
VisBeatAssets/VideoSources/animation.mp4/Data/Features/video/directogram_powers/animation_maxheight_360.pkl
VisBeatAssets/VideoSources/animation.mp4/Versions/.DS_Store
VisBeatAssets/VideoSources/animation.mp4/Versions/Original/.DS_Store
VisBeatAssets/VideoSources/animation.mp4/Versions/Original/maxheight_360/animation.mp4
VisBeatAssets/VideoSources/animation.mp4/Versions/Source/Full/animation.mp4
VisBeatAssets/VideoSources/demo-new.mp4/VideoSource.json
VisBeatAssets/VideoSources/demo-new.mp4/Data/Backups/VideoSource.json
VisBeatAssets/VideoSources/demo-new.mp4/Data/Features/video/directogram_powers/demo-new_maxheight_360.pkl
VisBeatAssets/VideoSources/demo-new.mp4/Versions/Original/maxheight_360/demo-new.mp4
VisBeatAssets/VideoSources/demo-new.mp4/Versions/Source/Full/demo-new.mp4
VisBeatAssets/VideoSources/final_640.mp4/VideoSource.json
VisBeatAssets/VideoSources/final_640.mp4/Data/Backups/VideoSource.json
VisBeatAssets/VideoSources/final_640.mp4/Data/Features/video/directogram_powers/final_640_maxheight_360.pkl
VisBeatAssets/VideoSources/final_640.mp4/Versions/Original/maxheight_360/final_640.mp4
VisBeatAssets/VideoSources/final_640.mp4/Versions/Source/Full/final_640.mp4
VisBeatAssets/VideoSources/wzk1_0.mp4/VideoSource.json
VisBeatAssets/VideoSources/wzk1_0.mp4/Data/Backups/VideoSource.json
VisBeatAssets/VideoSources/wzk1_0.mp4/Data/Features/video/directogram_powers/wzk1_0_maxheight_360.pkl
VisBeatAssets/VideoSources/wzk1_0.mp4/Versions/Original/maxheight_360/wzk1_0.mp4
VisBeatAssets/VideoSources/wzk1_0.mp4/Versions/Source/Full/wzk1_0.mp4
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238/.DS_Store
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238/VideoSource.json
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238.mp4/.DS_Store
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238.mp4/VideoSource.json
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238.mp4/Data/.DS_Store
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238.mp4/Versions/.DS_Store
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238/Data/.DS_Store
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238/Data/Backups/VideoSource.json
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238/Data/Features/video/directogram_powers/wzk_vlog_beat_enhance1_track1238_maxheight_360.pkl
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238/Versions/.DS_Store
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238/Versions/Original/maxheight_360/wzk_vlog_beat_enhance1_track1238.mp4
VisBeatAssets/VideoSources/wzk_vlog_beat_enhance1_track1238/Versions/Source/Full/wzk_vlog_beat_enhance1_track1238.mp4
VisBeatAssets/VideoSources/zly2_0.mp4/.DS_Store
VisBeatAssets/VideoSources/zly2_0.mp4/VideoSource.json
VisBeatAssets/VideoSources/zly2_0.mp4/Data/.DS_Store
VisBeatAssets/VideoSources/zly2_0.mp4/Data/Backups/VideoSource.json
VisBeatAssets/VideoSources/zly2_0.mp4/Data/Features/video/directogram_powers/zly2_0_maxheight_360.pkl
VisBeatAssets/VideoSources/zly2_0.mp4/Versions/.DS_Store
VisBeatAssets/VideoSources/zly2_0.mp4/Versions/Original/maxheight_360/zly2_0.mp4
VisBeatAssets/VideoSources/zly2_0.mp4/Versions/Source/Full/zly2_0.mp4
VisBeatAssets/VideoSources/zly3_0.mp4/VideoSource.json
VisBeatAssets/VideoSources/zly3_0.mp4/Versions/Source/Full/zly3_0.mp4
bin/dancefer
visbeat3/.DS_Store
visbeat3/ADefines.py
visbeat3/AFileManager.py
visbeat3/AFuncDict.py
visbeat3/AImports.py
visbeat3/AObject.py
visbeat3/AParamDict.py
visbeat3/Audio.py
visbeat3/AudioClip.py
visbeat3/Event.py
visbeat3/EventList.py
visbeat3/Image.py
visbeat3/Image_CV.py
visbeat3/SourceLocationParser.py
visbeat3/TimeSignal.py
visbeat3/TimeSignal1D.py
visbeat3/VBMIDI.py
visbeat3/VBObject.py
visbeat3/Video.py
visbeat3/VideoClip.py
visbeat3/VideoSource.py
visbeat3/Video_CV.py
visbeat3/VisBeatDefines.py
visbeat3/VisBeatExampleVideo.py
visbeat3/VisBeatImports.py
visbeat3/VisualBeat.py
visbeat3/Warp.py
visbeat3/__init__.py
visbeat3/_dancefer_examples.py
visbeat3/_dancify_examples.py
visbeat3/_mediafiles.py
visbeat3/_music_examples.py
visbeat3/command_line.py
visbeat3.egg-info/PKG-INFO
visbeat3.egg-info/SOURCES.txt
visbeat3.egg-info/dependency_links.txt
visbeat3.egg-info/requires.txt
visbeat3.egg-info/top_level.txt
visbeat3/__pycache__/ADefines.cpython-37.pyc
visbeat3/__pycache__/AFileManager.cpython-37.pyc
visbeat3/__pycache__/AFuncDict.cpython-37.pyc
visbeat3/__pycache__/AImports.cpython-37.pyc
visbeat3/__pycache__/AObject.cpython-37.pyc
visbeat3/__pycache__/AParamDict.cpython-37.pyc
visbeat3/__pycache__/Audio.cpython-37.pyc
visbeat3/__pycache__/AudioClip.cpython-37.pyc
visbeat3/__pycache__/Event.cpython-37.pyc
visbeat3/__pycache__/EventList.cpython-37.pyc
visbeat3/__pycache__/Image.cpython-37.pyc
visbeat3/__pycache__/Image_CV.cpython-37.pyc
visbeat3/__pycache__/SourceLocationParser.cpython-37.pyc
visbeat3/__pycache__/TimeSignal.cpython-37.pyc
visbeat3/__pycache__/TimeSignal1D.cpython-37.pyc
visbeat3/__pycache__/VBObject.cpython-37.pyc
visbeat3/__pycache__/Video.cpython-37.pyc
visbeat3/__pycache__/VideoClip.cpython-37.pyc
visbeat3/__pycache__/VideoSource.cpython-37.pyc
visbeat3/__pycache__/Video_CV.cpython-37.pyc
visbeat3/__pycache__/VisBeatDefines.cpython-37.pyc
visbeat3/__pycache__/VisBeatExampleVideo.cpython-37.pyc
visbeat3/__pycache__/VisBeatImports.cpython-37.pyc
visbeat3/__pycache__/VisualBeat.cpython-37.pyc
visbeat3/__pycache__/Warp.cpython-37.pyc
visbeat3/__pycache__/__init__.cpython-37.pyc
visbeat3/__pycache__/_mediafiles.cpython-37.pyc
visbeat3/assets/audio/hit.wav
visbeat3/assets/images/VisBeatWatermark.png
visbeat3/fileui/__init__.py
visbeat3/fileui/uipath.py
visbeat3/fileui/__pycache__/__init__.cpython-37.pyc
visbeat3/fileui/__pycache__/uipath.cpython-37.pyc
visbeat3/vbgui/BeatGUI.py
visbeat3/vbgui/__init__.py
visbeat3/vbgui/__pycache__/BeatGUI.cpython-37.pyc
visbeat3/vbgui/__pycache__/__init__.cpython-37.pyc
================================================
FILE: src/video2npz/visbeat3/visbeat3.egg-info/dependency_links.txt
================================================
================================================
FILE: src/video2npz/visbeat3/visbeat3.egg-info/requires.txt
================================================
numpy
scipy
bs4
librosa
imageio
requests
moviepy
termcolor
youtube-dl
matplotlib
================================================
FILE: src/video2npz/visbeat3/visbeat3.egg-info/top_level.txt
================================================
visbeat3
================================================
FILE: videos/.gitkeep
================================================