Coverage for src/code_beatrix/art/moviepy_context.py: 68%
87 statements
« prev ^ index » next coverage.py v7.1.0, created at 2023-04-29 13:45 +0200
« prev ^ index » next coverage.py v7.1.0, created at 2023-04-29 13:45 +0200
1# -*- coding: utf-8 -*-
2"""
3@file
4@brief Quelques questions d'ordre général autour du langage Python.
5"""
6import os
7from moviepy.audio.AudioClip import AudioClip
8from moviepy.video.VideoClip import VideoClip
9from moviepy.editor import VideoFileClip, AudioFileClip
12class VideoContext:
13 """
14 Creates a context for a :epkg:`VideoClip`.
15 It deals with opening, closing subprocesses.
17 @return :epkg:`VideoClip`
18 """
20 def __init__(self, video_or_file):
21 """
22 @param video_or_file string or :epkg:`VideoClip`
23 """
24 if isinstance(video_or_file, VideoContext):
25 self.video_or_file = video_or_file.video
26 else:
27 self.video_or_file = video_or_file
29 def __enter__(self):
30 """
31 Enters the context.
32 """
33 if isinstance(self.video_or_file, str):
34 if not os.path.exists(self.video_or_file):
35 raise FileNotFoundError(self.video_or_file)
36 video = VideoFileClip(self.video_or_file)
37 self.close = True
38 elif isinstance(self.video_or_file, VideoClip):
39 video = self.video_or_file
40 self.close = False
41 elif isinstance(self.video_or_file, VideoContext):
42 raise TypeError("Video cannot be a VideoContext")
43 else:
44 raise TypeError(
45 'Unable to use type {0}'.format(type(self.video_or_file)))
46 self.video = video
47 return self
49 def __exit__(self, *exc):
50 """
51 Leaves the context.
52 """
53 if exc and len(exc) == 3 and exc[1] is not None:
54 raise exc[1]
55 if self.close:
56 del self.video
57 return False
59 def __getattr__(self, fct):
60 """
61 Retrieves a method in :epkg:`VideoClip`.
63 @param fct method name
64 @return method
65 """
66 if not hasattr(self.video, fct):
67 raise AttributeError(
68 "Unable to find method '{0}' in {1}".format(fct, type(self.video)))
69 return getattr(self.video, fct)
72class AudioContext:
73 """
74 Creates a context for a :epkg:`AudioClip`.
76 @return :epkg:`AudioClip`
77 """
79 def __init__(self, audio_or_file):
80 """
81 @param audio_or_file string or :epkg:`AudioClip`
82 """
83 if isinstance(audio_or_file, AudioContext):
84 self.audio_or_file = audio_or_file.audio
85 else:
86 self.audio_or_file = audio_or_file
88 def __enter__(self):
89 """
90 Enters the context.
91 """
92 if isinstance(self.audio_or_file, str):
93 if not os.path.exists(self.audio_or_file):
94 raise FileNotFoundError(self.audio_or_file)
95 audio = AudioFileClip(self.audio_or_file)
96 self.close = True
97 elif isinstance(self.audio_or_file, AudioClip):
98 audio = self.audio_or_file
99 self.close = False
100 elif isinstance(self.audio_or_file, AudioContext):
101 raise TypeError("Audio cannot be a VideoContext")
102 else:
103 raise TypeError(
104 'Unable to use type {0}'.format(type(self.audio_or_file)))
105 self.audio = audio
106 return self
108 def __exit__(self, *exc):
109 """
110 Leaves the context.
111 """
112 if exc and len(exc) == 3 and exc[1] is not None:
113 raise exc[1]
114 return False
116 def __getattr__(self, fct):
117 """
118 Retrieves a method in :epkg:`AudioClip`.
120 @param fct method name
121 @return method
122 """
123 if not hasattr(self.audio, fct):
124 raise AttributeError(
125 "Unable to find method '{0}' in {1}".format(fct, type(self.audio)))
126 return getattr(self.audio, fct)
129def get_wrapped(obj):
130 """
131 Retrives the video or the audio wrapped or not wrapped into obj.
133 @param obj @see cl WrappedObject, @see cl AudioContext, @see cl VideoContext
134 @return wrapped object
135 """
136 if isinstance(obj, VideoContext):
137 return obj.video
138 elif isinstance(obj, AudioContext):
139 return obj.audio
140 else:
141 return obj
144def clean_video(video):
145 """
146 Cleans residual open streams.
147 It is related to the following issues:
149 * `The handle is invalid - Windows Only <https://github.com/Zulko/moviepy/issues/697>`_
150 """
151 if isinstance(video, (str, bool, int, float)):
152 raise TypeError("Unexpected type ({0})".format(type(video)))
153 if isinstance(video, list):
154 for v in video:
155 clean_video(v)
156 else:
157 if not hasattr(video, 'close'):
158 if hasattr(video, 'reader') and video.reader:
159 try:
160 video.reader.close()
161 video.reader = None
162 except AttributeError:
163 pass
164 try:
165 if video.audio:
166 video.audio.close()
167 video.audio = None
168 except AttributeError:
169 pass
170 else:
171 video.close()
172 # ~ if hasattr(video, 'reader'):
173 #~ video.reader.close()
174 # ~ if hasattr(video.audio, 'reader'):
175 #~ video.audio.reader.close_proc()