Hi everyone,
Let me know is there any option to export animation and save it in a video format like mp4,mpeg or…? if answer is yes is there any link to guide me?
With Best,
Hi everyone,
Let me know is there any option to export animation and save it in a video format like mp4,mpeg or…? if answer is yes is there any link to guide me?
With Best,
Hi @Bijan,
A plotly animation cannot be saved, directly, but there are two methods to create a video or a gif file from frames.
go.Frame
,The pngs files are uploaded to ezgif, https://ezgif.com/maker, to create a gif file
by setting correspondingly the Delay time
.
Save the gif file on your system, and then upload it again to ezgif,
[Online GIF to MP4 Video converter] (Online GIF to MP4 Video converter) to convert the gif to a mp4 file.
Example:
import meshio
import numpy as np
from numpy import pi, sin, cos
import plotly.graph_objects as go
import plotly.io as pio
msh = meshio.read("face-mesh.obj") #https://raw.githubusercontent.com/empet/Datasets/master/Meshes/face-mesh.obj
verts = msh.points
middle = np.max(verts, axis=0) + np.min(verts, axis=0)/2
verts = verts - middle
I, J, K = msh.cells_dict["triangle"].T
x, y, z = verts.T
colorscale = [[0, 'rgb(250,250,250)'],
[1, 'rgb(250,250,250)']]
figanim = go.Figure(go.Mesh3d(x=x, y=y, z=z,
i=I, j=J, k=K,
intensity=z,
colorscale =colorscale,
showscale=False,
lighting=dict(ambient=0.1,
diffuse=1,
fresnel=3,
specular=0.5,
roughness=0.05),
lightposition=dict(x=100,
y=200,
z=1000)
))
axis_prop =dict(visible=False, autorange=False)
scenes = dict(xaxis=dict(range=[-11.41, 11.41], **axis_prop),
yaxis=dict(range=[-11.41, 11.41], **axis_prop),
zaxis=dict(range=[-14.67, 4.37], **axis_prop),
camera_eye=dict(x=-1.85, y=-1.85, z=0.65),
aspectratio=dict(x=1.15, y=1.15, z=1.1))
figanim.update_layout(title_text="Hollow mask illusion", title_x=0.5, title_y=0.95,
font_size=16, font_color="white",
width=400, height=400, autosize=False,
margin=dict(t=2, r=2, b=2, l=2), #IMPORTANT to set only 2 pixels margin because
#otherwise around each png there is a two big white space
paper_bgcolor='black',
scene= scenes)
figanim.show()
######### Below are the code lines corresponding to "animation", i.e. to creating a png file
######### for each frame
def RotZ(t):
return np.array([[cos(t), -sin(t), 0],
[sin(t), cos(t), 0],
[0, 0, 1]])
t = np.linspace(0, 2*pi, 73)
for k, s in enumerate(t):
xr, yr, zr = RotZ(-s) @ verts.T
figanim.update_traces(x=xr, y=yr, z=zr)#this line is equivalent to go.Frame; It creates the png corresponding to a frame
pio.write_image(figanim, f"images/{k+1:03d}.png", width=400, height=400, scale=1)#save the frame as png file in the folder images
This is the corresponding video: https://imgur.com/a/VRUw4AN
moviepy
https://github.com/Zulko/moviepy
Install it with pip:
pip install moviepy
Below is an example I created two years ago. I hope it still works, because meantime I uninstalled Python and many packages, and reinstalled only those I’m working with.
import numpy as np
from scipy.spatial import Delaunay
import plotly.graph_objects as go
import moviepy.editor as mpy
import io
from PIL import Image
def plotly_fig2array(fig):
#convert Plotly fig to an array
fig_bytes = fig.to_image(format="png")
buf = io.BytesIO(fig_bytes)
img = Image.open(buf)
return np.asarray(img)
n = 20 # number of radii
h = 2/(n-1)
r = np.linspace(h, 2, n)
theta = np.linspace(0, 2*np.pi, 60)
r, theta = np.meshgrid(r,theta)
r = r.flatten()
theta = theta.flatten()
x = r*np.cos(theta)
y = r*np.sin(theta)
# Triangulate the circular planar region
tri = Delaunay(np.vstack([x,y]).T)
faces = np.asarray(tri.simplices)
I, J, K = faces.T
f = lambda h: np.sinc(x**2+y**2)+np.sin(x+h)
fig = go.Figure(go.Mesh3d(x=x,
y=y,
z=f(0),
intensity=f(0),
i=I,
j=J,
k=K,
colorscale='matter_r',
showscale=False))
fig.update_layout(title_text='My hat is flying with MoviePy',
title_x=0.5,
width=500, height=500,
scene_xaxis_visible=False,
scene_yaxis_visible=False,
scene_zaxis_visible=False)
# No Plotly frames are defined here!! Instead we define moviepy frames by
# converting each Plotly figure to an array, from which MoviePy creates a clip
# The concatenated clips are saved as a gif file:
def make_frame(t):
z = f(2*np.pi*t/2)
fig.update_traces(z=z, intensity=z) #These are the updates that usually are performed within Plotly go.Frame definition
return plotly_fig2array(fig)
animation = mpy.VideoClip(make_frame, duration=2)
animation.write_gif("image/my_hat.gif", fps=20)
Search in moviepy docs to find out how to save the VideoClip as a mp4 file.
This is the resulted gif: https://imgur.com/a/s3p4iNU
and this one https://imgur.com/a/Ebbao7f the corresponding video
Dear @empet really thanks for this complete answer and also useful answer.
Seems in second code the below Function that has been written by you (@empet) is missed, So I put it here for make this page complete for the others. Again Thank you @empet .
import io
from PIL import Image
def plotly_fig2array(fig):
#convert Plotly fig to an array
fig_bytes = fig.to_image(format="png")
buf = io.BytesIO(fig_bytes)
img = Image.open(buf)
return np.asarray(img)
@Bijan I’ve lost this function during the copy-paste process. I inserted it now, to have all code available. Thanks for pointing it out.