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

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 

10 

11 

12class VideoContext: 

13 """ 

14 Creates a context for a :epkg:`VideoClip`. 

15 It deals with opening, closing subprocesses. 

16 

17 @return :epkg:`VideoClip` 

18 """ 

19 

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 

28 

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 

48 

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 

58 

59 def __getattr__(self, fct): 

60 """ 

61 Retrieves a method in :epkg:`VideoClip`. 

62 

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) 

70 

71 

72class AudioContext: 

73 """ 

74 Creates a context for a :epkg:`AudioClip`. 

75 

76 @return :epkg:`AudioClip` 

77 """ 

78 

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 

87 

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 

107 

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 

115 

116 def __getattr__(self, fct): 

117 """ 

118 Retrieves a method in :epkg:`AudioClip`. 

119 

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) 

127 

128 

129def get_wrapped(obj): 

130 """ 

131 Retrives the video or the audio wrapped or not wrapped into obj. 

132 

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 

142 

143 

144def clean_video(video): 

145 """ 

146 Cleans residual open streams. 

147 It is related to the following issues: 

148 

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()