from pylab import *
from moviepy.editor import TextClip, CompositeVideoClip, ImageClip, AudioFileClip, VideoFileClip
from moviepy.editor import concatenate as concat_clips
There's a discussion about which size is better for generating a clip. Below is something I found on the internet.
screensize = (854, 480)
First, we load the sound and do the boilerplate stuff.
# load sound file
from scipy.io import wavfile
sample_freq, whistle = wavfile.read("samsung_ringtone.wav")
t = arange(whistle.shape[0], dtype=float32) / sample_freq
# segment it
chunk_times = [0., 0.22, 0.38, 0.5, 0.92, 1.2]
from scipy.signal import get_window
chunks = []
for start, end in zip(chunk_times[:-1], chunk_times[1:]):
chunks.append(whistle[(t > start) & (t < end)] * get_window('hamming', t[(t > start) & (t < end)].size))
# make the permutations
from itertools import permutations
from collections import OrderedDict
variations = OrderedDict()
for p in permutations((0, 1, 2, 3, 4)):
out = []
for elem in p:
if len(out) == 0:
out = chunks[elem].copy()
else:
out = concatenate((out, chunks[elem].copy()))
variations[str(p)] = out.copy()
Now we define our export functions.
def generate_image(audio_clip, sample_freq, title_label, filename='tmp.png'):
""" plots the waveform and the spectrogram of the audio clip
and saves it to disk
"""
dpi = 100.
t = arange(audio_clip.shape[0], dtype=float32) / sample_freq
f = figure(1, figsize=(screensize[0]/dpi, screensize[1]/dpi))
clf()
subplot(211)
plot(t, audio_clip)
xlabel("time (s)")
ylabel('amplitude (a. u.)')
title(title_label)
grid(True)
subplot(212)
specgram(audio_clip, Fs=sample_freq)
xlim(0, 1.1)
ylim(0, 10000)
xlabel('time (s)')
ylabel('frequency (Hz)')
tight_layout()
savefig(filename, dpi=dpi)
def generate_audio(variation, sample_freq, filename='sound.wav'):
wavfile.write(filename, sample_freq, variation.astype(int16))
Now we can loop over the different elements and save them to disk.
key2filename = lambda k: k[1:-1].replace(', ', '_')
%%time
if True:
for p in variations.keys():
generate_image(variations[p], sample_freq, p, filename="img/"+key2filename(p)+".png")
for p in variations.keys():
generate_audio(variations[p], sample_freq, filename="snd/"+key2filename(p)+".wav")
The final clip is built below. Due to memory issues, it's built in two steps.
Firts, we write a function that can generate the two bits of the video. Then we join them together.
# display available fonts on system
#TextClip.list('font')
def partial_loop(start, n, filename):
clips = []
# intro screen
if start == 0:
intro_txt = TextClip("""119 Variations\non a theme by Samsung\n'The whistling ringtone'""",
color='white',
font='Baskerville-Old-Face',
kerning=5,
fontsize=50).set_pos('center').set_duration(5)
intro_cvc = CompositeVideoClip( [intro_txt],
size=screensize, transparent=True)
clips.append(intro_cvc)
# loop
cnt = start
for p in variations.keys()[start: start + n]:
cnt += 1
print cnt,
# title
clips.append(CompositeVideoClip([TextClip(p,
color='white',
fontsize=50,
font='Baskerville-Old-Face').set_pos('center').set_duration(2)],
size=screensize))
# the image and sound
aud_clip = AudioFileClip("snd/"+key2filename(p)+".wav", fps=sample_freq)
im_clip = ImageClip("img/"+key2filename(p)+".png")
im_clip = im_clip.set_audio(aud_clip).set_duration(aud_clip.duration)
clips.append(CompositeVideoClip([im_clip],
size=screensize))
# concatenation and output
video = concat_clips(clips)
video.to_videofile(filename + ".avi", codec='mpeg4')
partial_loop(0, 50, "SamsungVariationsPart1")
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 MoviePy: building video file SamsungVariationsPart1.avi ---------------------------------------- Writing audio in SamsungVariationsPart1TEMP_MPY_to_videofile_SOUND.ogg Done writing Audio in SamsungVariationsPart1TEMP_MPY_to_videofile_SOUND.ogg ! Writing video into SamsungVariationsPart1TEMP_MPY_to_videofile.avi Done writing video in SamsungVariationsPart1TEMP_MPY_to_videofile.avi ! Now merging video and audio: MoviePy Running: >>> ffmpeg -y -i SamsungVariationsPart1TEMP_MPY_to_videofile_SOUND.ogg -i SamsungVariationsPart1TEMP_MPY_to_videofile.avi -vcodec copy -acodec copy SamsungVariationsPart1.avi ... command successful. Your video is ready ! Fingers crossed for the Oscars !
partial_loop(50, 70, "SamsungVariationsPart2")
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 MoviePy: building video file SamsungVariationsPart2.avi ---------------------------------------- Writing audio in SamsungVariationsPart2TEMP_MPY_to_videofile_SOUND.ogg Done writing Audio in SamsungVariationsPart2TEMP_MPY_to_videofile_SOUND.ogg ! Writing video into SamsungVariationsPart2TEMP_MPY_to_videofile.avi Done writing video in SamsungVariationsPart2TEMP_MPY_to_videofile.avi ! Now merging video and audio: MoviePy Running: >>> ffmpeg -y -i SamsungVariationsPart2TEMP_MPY_to_videofile_SOUND.ogg -i SamsungVariationsPart2TEMP_MPY_to_videofile.avi -vcodec copy -acodec copy SamsungVariationsPart2.avi ... command successful. Your video is ready ! Fingers crossed for the Oscars !
We can now join the two parts together.
part1 = VideoFileClip("SamsungVariationsPart1.avi")
part2 = VideoFileClip("SamsungVariationsPart2.avi")
final_clip = concat_clips([part1, part2])
final_clip.to_videofile("SamsungVariations.avi")
MoviePy: building video file SamsungVariations.avi ---------------------------------------- Writing audio in SamsungVariationsTEMP_MPY_to_videofile_SOUND.ogg Done writing Audio in SamsungVariationsTEMP_MPY_to_videofile_SOUND.ogg ! Writing video into SamsungVariationsTEMP_MPY_to_videofile.avi Done writing video in SamsungVariationsTEMP_MPY_to_videofile.avi ! Now merging video and audio: MoviePy Running: >>> ffmpeg -y -i SamsungVariationsTEMP_MPY_to_videofile_SOUND.ogg -i SamsungVariationsTEMP_MPY_to_videofile.avi -vcodec copy -acodec copy SamsungVariations.avi ... command successful. Your video is ready ! Fingers crossed for the Oscars !