ai-content-maker/.venv/Lib/site-packages/moviepy/video/io/html_tools.py

222 lines
7.4 KiB
Python
Raw Permalink Normal View History

2024-05-11 23:00:43 +03:00
"""
This module implements ipython_display
A function to embed images/videos/audio in the IPython Notebook
"""
# Notes:
# All media are physically embedded in the IPython Notebook
# (instead of simple links to the original files)
# That is because most browsers use a cache system and they won't
# properly refresh the media when the original files are changed.
import os
from base64 import b64encode
from moviepy.audio.AudioClip import AudioClip
from moviepy.tools import extensions_dict
from ..VideoClip import ImageClip, VideoClip
from .ffmpeg_reader import ffmpeg_parse_infos
try:
from IPython.display import HTML
ipython_available = True
class HTML2(HTML):
def __add__(self, other):
return HTML2(self.data+other.data)
except ImportError:
ipython_available = False
sorry = "Sorry, seems like your browser doesn't support HTML5 audio/video"
templates = {"audio":("<audio controls>"
"<source %(options)s src='data:audio/%(ext)s;base64,%(data)s'>"
+sorry+"</audio>"),
"image":"<img %(options)s "
"src='data:image/%(ext)s;base64,%(data)s'>",
"video":("<video %(options)s"
"src='data:video/%(ext)s;base64,%(data)s' controls>"
+sorry+"</video>")}
def html_embed(clip, filetype=None, maxduration=60, rd_kwargs=None,
center=True, **html_kwargs):
""" Returns HTML5 code embedding the clip
clip
Either a file name, or a clip to preview.
Either an image, a sound or a video. Clips will actually be
written to a file and embedded as if a filename was provided.
filetype
One of 'video','image','audio'. If None is given, it is determined
based on the extension of ``filename``, but this can bug.
rd_kwargs
keyword arguments for the rendering, like {'fps':15, 'bitrate':'50k'}
**html_kwargs
Allow you to give some options, like width=260, autoplay=True,
loop=1 etc.
Examples
=========
>>> import moviepy.editor as mpy
>>> # later ...
>>> clip.write_videofile("test.mp4")
>>> mpy.ipython_display("test.mp4", width=360)
>>> clip.audio.write_audiofile('test.ogg') # Sound !
>>> mpy.ipython_display('test.ogg')
>>> clip.write_gif("test.gif")
>>> mpy.ipython_display('test.gif')
>>> clip.save_frame("first_frame.jpeg")
>>> mpy.ipython_display("first_frame.jpeg")
"""
if rd_kwargs is None:
rd_kwargs = {}
if "Clip" in str(clip.__class__):
TEMP_PREFIX = "__temp__"
if isinstance(clip,ImageClip):
filename = TEMP_PREFIX+".png"
kwargs = {'filename':filename, 'withmask':True}
kwargs.update(rd_kwargs)
clip.save_frame(**kwargs)
elif isinstance(clip,VideoClip):
filename = TEMP_PREFIX+".mp4"
kwargs = {'filename':filename, 'verbose':False, 'preset':'ultrafast'}
kwargs.update(rd_kwargs)
clip.write_videofile(**kwargs)
elif isinstance(clip,AudioClip):
filename = TEMP_PREFIX+".mp3"
kwargs = {'filename': filename, 'verbose':False}
kwargs.update(rd_kwargs)
clip.write_audiofile(**kwargs)
else:
raise ValueError("Unknown class for the clip. Cannot embed and preview.")
return html_embed(filename, maxduration=maxduration, rd_kwargs=rd_kwargs,
center=center, **html_kwargs)
filename = clip
options = " ".join(["%s='%s'"%(str(k), str(v)) for k,v in html_kwargs.items()])
name, ext = os.path.splitext(filename)
ext = ext[1:]
if filetype is None:
ext = filename.split('.')[-1].lower()
if ext == "gif":
filetype = 'image'
elif ext in extensions_dict:
filetype = extensions_dict[ext]['type']
else:
raise ValueError("No file type is known for the provided file. Please provide "
"argument `filetype` (one of 'image', 'video', 'sound') to the "
"ipython display function.")
if filetype== 'video':
# The next lines set the HTML5-cvompatible extension and check that the
# extension is HTML5-valid
exts_htmltype = {'mp4': 'mp4', 'webm':'webm', 'ogv':'ogg'}
allowed_exts = " ".join(exts_htmltype.keys())
try:
ext = exts_htmltype[ext]
except:
raise ValueError("This video extension cannot be displayed in the "
"IPython Notebook. Allowed extensions: "+allowed_exts)
if filetype in ['audio', 'video']:
duration = ffmpeg_parse_infos(filename)['duration']
if duration > maxduration:
raise ValueError("The duration of video %s (%.1f) exceeds the 'maxduration' "%(filename, duration)+
"attribute. You can increase 'maxduration', by passing 'maxduration' parameter"
"to ipython_display function."
"But note that embedding large videos may take all the memory away !")
with open(filename, "rb") as f:
data= b64encode(f.read()).decode("utf-8")
template = templates[filetype]
result = template%{'data':data, 'options':options, 'ext':ext}
if center:
result = r"<div align=middle>%s</div>"%result
return result
def ipython_display(clip, filetype=None, maxduration=60, t=None, fps=None,
rd_kwargs=None, center=True, **html_kwargs):
"""
clip
Either the name of a file, or a clip to preview. The clip will
actually be written to a file and embedded as if a filename was
provided.
filetype:
One of 'video','image','audio'. If None is given, it is determined
based on the extension of ``filename``, but this can bug.
maxduration
An error will be raised if the clip's duration is more than the indicated
value (in seconds), to avoid spoiling the browser's cache and the RAM.
t
If not None, only the frame at time t will be displayed in the notebook,
instead of a video of the clip
fps
Enables to specify an fps, as required for clips whose fps is unknown.
**kwargs:
Allow you to give some options, like width=260, etc. When editing
looping gifs, a good choice is loop=1, autoplay=1.
Remarks: If your browser doesn't support HTML5, this should warn you.
If nothing is displayed, maybe your file or filename is wrong.
Important: The media will be physically embedded in the notebook.
Examples
=========
>>> import moviepy.editor as mpy
>>> # later ...
>>> clip.write_videofile("test.mp4")
>>> mpy.ipython_display("test.mp4", width=360)
>>> clip.audio.write_audiofile('test.ogg') # Sound !
>>> mpy.ipython_display('test.ogg')
>>> clip.write_gif("test.gif")
>>> mpy.ipython_display('test.gif')
>>> clip.save_frame("first_frame.jpeg")
>>> mpy.ipython_display("first_frame.jpeg")
"""
if not ipython_available:
raise ImportError("Only works inside an IPython Notebook")
if rd_kwargs is None:
rd_kwargs = {}
if fps is not None:
rd_kwargs['fps'] = fps
if t is not None:
clip = clip.to_ImageClip(t)
return HTML2(html_embed(clip, filetype=filetype, maxduration=maxduration,
center=center, rd_kwargs=rd_kwargs, **html_kwargs))