choix de cloche et vidéo gif fonctionnelle

This commit is contained in:
Francois Pelletier 2023-04-02 12:15:59 -04:00
parent eae8367550
commit 55340872df
6 changed files with 97 additions and 15 deletions

View file

@ -19,8 +19,5 @@ RUN pip install -r requirements.txt
COPY *.py ./
RUN python install.py
# Copy the app's code
COPY main.py .
# Run the application
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

39
animate_fractal.py Normal file
View file

@ -0,0 +1,39 @@
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from mandelbrot import mandelbrot
def animategif():
x_start, y_start = -2, -1.5 # an interesting region starts here
width, height = 3, 3 # for 3 units up and right
density_per_unit = 100 # how many pixels per unit
# real and imaginary axis
re = np.linspace(x_start, x_start + width, width * density_per_unit)
im = np.linspace(y_start, y_start + height, height * density_per_unit)
fig = plt.figure(figsize=(5, 5)) # instantiate a figure to draw
ax = plt.axes() # create an axes object
def animate(i):
ax.clear() # clear axes object
ax.set_xticks([], []) # clear x-axis ticks
ax.set_yticks([], []) # clear y-axis ticks
X = np.empty((len(re), len(im))) # re-initialize the array-like image
threshold = round(1.15 ** (i + 1)) # calculate the current threshold
# iterations for the current threshold
for i in range(len(re)):
for j in range(len(im)):
X[i, j] = mandelbrot(re[i], im[j], threshold)
# associate colors to the iterations with an iterpolation
img = ax.imshow(X.T, interpolation="bicubic", cmap='magma')
return [img]
anim = animation.FuncAnimation(fig, animate, frames=45, interval=120, blit=True)
return anim

47
main.py
View file

@ -9,6 +9,7 @@ from AccelBrainBeat.brainbeat.binaural_beat import BinauralBeat
import pydub
import random
from animate_fractal import animategif
from blend_av import blend_av
app = FastAPI()
@ -37,7 +38,7 @@ class VideoProperties(BaseModel):
main_frequency: int
breath_pattern_in: int
breath_pattern_out: int
color_palette = str
color_scheme = str
class AvProperties(BaseModel):
@ -66,12 +67,11 @@ async def get_generate_audio(audio_properties: AudioProperties):
:param audio_properties:
:return:
"""
# Generate a random 32 hexadecimal string
tmp_dir = pathlib.Path("tmp_sound")
tmp_dir.mkdir(parents=True, exist_ok=True)
# Remove existing files in tmp_dir
for filename in os.listdir(tmp_dir):
os.remove(str(tmp_dir / filename))
os.remove(tmp_dir / str(filename))
bell_dir = pathlib.Path("bell")
filename_prefix = ''.join([random.choice('0123456789ABCDEF') for i in range(32)])
filename = f"{filename_prefix}.wav"
@ -80,18 +80,32 @@ async def get_generate_audio(audio_properties: AudioProperties):
b.save_beat(output_file_name=str(tmp_dir / "binaural_beat.wav"),
frequencys=(audio_properties.main_frequency,
audio_properties.lag_frequency),
play_time=(audio_properties.breath_pattern_in + audio_properties.breath_pattern_out)*2,
play_time=(audio_properties.breath_pattern_in + audio_properties.breath_pattern_out) * 2,
volume=audio_properties.volume
)
pydub_background = pydub.AudioSegment.from_wav(tmp_dir / "binaural_beat.wav")
pydub_bell = pydub.AudioSegment.from_wav(bell_dir / audio_properties.bell_sound)
pydub_mix = pydub_background. \
overlay(pydub_bell, position=0). \
overlay(pydub_bell, position=audio_properties.breath_pattern_in * 1000). \
overlay(pydub_bell, position=(audio_properties.breath_pattern_in+audio_properties.breath_pattern_out) * 1000). \
overlay(pydub_bell, position=(audio_properties.breath_pattern_in*2+audio_properties.breath_pattern_out) * 1000)
bell_file = ""
if audio_properties.bell_sound == "Cloche":
bell_file = "339810__inspectorj__hand-bells-a-single-mod.wav"
skip_bell = False
elif audio_properties.bell_sound == "Bol tibétain":
bell_file = "417116__dersinnsspace__tibetan-bowl_right-hit-mod.wav"
skip_bell = False
else:
skip_bell = True
if skip_bell:
pydub_mix = pydub_background
else:
pydub_bell = pydub.AudioSegment.from_wav(bell_dir / bell_file)
pydub_mix = pydub_background. \
overlay(pydub_bell, position=0). \
overlay(pydub_bell, position=audio_properties.breath_pattern_in * 1000). \
overlay(pydub_bell,
position=(audio_properties.breath_pattern_in + audio_properties.breath_pattern_out) * 1000). \
overlay(pydub_bell,
position=(audio_properties.breath_pattern_in * 2 + audio_properties.breath_pattern_out) * 1000)
pydub_mix.export(tmp_dir / filename, format="wav")
return filename
return FileResponse(tmp_dir / filename)
@app.get("/generate_video")
@ -101,7 +115,16 @@ async def get_generate_video(video_properties: VideoProperties):
:param video_properties:
:return:
"""
return None
tmp_dir = pathlib.Path("tmp_video")
tmp_dir.mkdir(parents=True, exist_ok=True)
# Remove existing files in tmp_dir
for filename in os.listdir(tmp_dir):
os.remove(tmp_dir / str(filename))
anim = animategif()
filename_prefix = ''.join([random.choice('0123456789ABCDEF') for i in range(32)])
filename = f"{filename_prefix}.gif"
anim.save(str(tmp_dir / filename), writer='imagemagick')
return FileResponse(str(tmp_dir / filename))
@app.get("/generate_av")

21
mandelbrot.py Normal file
View file

@ -0,0 +1,21 @@
# Source: https://matplotlib.org/matplotblog/posts/animated-fractals/
def mandelbrot(x, y, threshold):
"""Calculates whether the number c = x + i*y belongs to the
Mandelbrot set. In order to belong, the sequence z[i + 1] = z[i]**2 + c
must not diverge after 'threshold' number of steps. The sequence diverges
if the absolute value of z[i+1] is greater than 4.
:param float x: the x component of the initial complex number
:param float y: the y component of the initial complex number
:param int threshold: the number of iterations to considered it converged
"""
# initial conditions
c = complex(x, y)
z = complex(0, 0)
for i in range(threshold):
z = z ** 2 + c
if abs(z) > 4.: # it diverged
return i
return threshold - 1 # it didn't diverge

View file

@ -5,3 +5,5 @@ starlette~=0.26.1
AccelBrainBeat~=1.0.5
httpx~=0.23.3
pydub~=0.25.1
numpy~=1.24.2
matplotlib~=3.7.1