Update for API change: scene.cursor_location -> scene.cursor.location
[blender-addons.git] / sequencer_kinoraw_tools / proxy_tools.py
blobe36bf0d07e81b6c589dc11bf2753e337db184893
1 # gpl: authors Carlos Padial, Turi Scandurra
3 import bpy
4 import os
5 from bpy.types import (
6 Operator,
7 Panel,
9 from bpy.props import IntProperty
10 import subprocess
11 from . import functions
14 proxy_qualities = [
15 ("1", "25%", ""), ("2", "50%", ""),
16 ("3", "75%", ""), ("4", "100%", ""),
17 ("5", "none", "")
21 # Functions
22 def setup_proxy(context, strip, size):
23 preferences = context.preferences
24 prefs = preferences.addons[__package__].preferences
26 # set up proxy settings
27 strip.use_proxy = True
29 if prefs.use_bi_custom_directory:
30 strip.use_proxy_custom_directory = True
31 filename = strip.filepath.rpartition("/")[2].rpartition(".")[0]
32 strip.proxy.directory = bpy.path.relpath(prefs.proxy_dir + filename)
33 else:
34 strip.use_proxy_custom_directory = False
36 if strip.use_proxy_custom_file is True:
37 strip.use_proxy_custom_file = False
39 strip.proxy.quality = prefs.quality
40 strip.proxy.timecode = prefs.timecode
42 if size == 5:
43 strip.use_proxy = False
44 strip.proxy.build_25 = False
45 strip.proxy.build_50 = False
46 strip.proxy.build_75 = False
47 strip.proxy.build_100 = False
49 else:
50 proxysuffix = proxy_qualities[size - 1][1].split("%")[0]
52 if (proxysuffix == "25"):
53 strip.proxy.build_25 = True
54 if (proxysuffix == "50"):
55 strip.proxy.build_50 = True
56 if (proxysuffix == "75"):
57 strip.proxy.build_75 = True
58 if (proxysuffix == "100"):
59 strip.proxy.build_100 = True
61 return {"FINISHED"}
64 def create_proxy(context, strip, size, res):
65 # calculate proxy resolution
66 div = 4 / size
67 newres = (int(int(res[0]) / div), int(int(res[1]) / div))
69 preferences = context.preferences
70 proxy_dir = preferences.addons[__package__].preferences.proxy_dir
71 scripts = preferences.addons[__package__].preferences.proxy_scripts
72 ffmpeg_command = preferences.addons[__package__].preferences.ffmpeg_command
74 functions.create_folder(proxy_dir)
76 if scripts:
77 commands = []
79 # get filename
80 if strip.type == "MOVIE":
81 filename = bpy.path.abspath(strip.filepath)
82 proxysuffix = proxy_qualities[size - 1][1].split("%")[0]
83 proxy_dir = bpy.path.abspath(proxy_dir)
84 newfilename = os.path.join(proxy_dir, filename.rpartition("/")[2])
85 fileoutput = newfilename.rpartition(".")[0] + "-" + proxysuffix + ".avi"
87 # default value for ffmpeg_command = "fmpeg -i {} -vcodec mjpeg -qv 1 -s {}x{} -y {}"
89 command = ffmpeg_command.format(filename, newres[0], newres[1], fileoutput)
90 print(command)
92 if scripts:
93 commands.append(command)
94 else:
95 # check for existing file
96 if not os.path.isfile(fileoutput):
97 subprocess.call(command, shell=True)
98 else:
99 print("File already exists")
101 # set up proxy settings
102 strip.use_proxy = True
103 try:
104 strip.use_proxy_custom_file = True
105 strip.proxy.filepath = bpy.path.relpath(fileoutput)
106 except:
107 pass
109 if (proxysuffix == "25"):
110 strip.proxy.build_25 = True
111 if (proxysuffix == "50"):
112 strip.proxy.build_50 = True
113 if (proxysuffix == "75"):
114 strip.proxy.build_75 = True
115 if (proxysuffix == "100"):
116 strip.proxy.build_100 = True
118 if scripts:
119 return commands
120 else:
121 return None
124 def create_proxy_scripts(scripts_dir, commands, strip_name=None):
126 functions.create_folder(bpy.path.abspath(scripts_dir))
127 for i in commands:
128 # print(i)
129 filename = "{}/proxy_script_{}.sh".format(scripts_dir, strip_name)
130 text_file = open(bpy.path.abspath(filename), "w")
131 # print(filename)
132 text_file.write(i)
133 text_file.close()
136 # classes
137 class CreateProxyOperator(Operator):
138 bl_idname = "sequencer.create_proxy_operator"
139 bl_label = "Create Proxy"
140 bl_description = ("Use ffmpeg to create a proxy from video\n"
141 "and setup proxies for selected strip")
142 bl_options = {'REGISTER', 'UNDO'}
144 size: IntProperty(
145 name="Proxy Size",
146 default=1
149 @classmethod
150 def poll(self, context):
151 strip = functions.act_strip(context)
152 scn = context.scene
153 if scn and scn.sequence_editor and scn.sequence_editor.active_strip:
154 return strip.type in ('MOVIE')
155 else:
156 return False
158 def execute(self, context):
159 preferences = context.preferences
160 proxy_scripts_path = preferences.addons[__package__].preferences.proxy_scripts_path
162 for strip in context.selected_editable_sequences:
163 # get resolution from active strip
164 try:
165 bpy.ops.sequencerextra.read_exif()
166 except:
167 pass
169 sce = context.scene
170 try:
171 res = sce['metadata'][0]['Composite:ImageSize'].split("x")
172 except:
173 res = (sce.render.resolution_x, sce.render.resolution_y)
175 commands = create_proxy(context, strip, self.size, res)
177 if commands is None:
178 # Update scene
179 context.scene.update()
180 newstrip = context.scene.sequence_editor.active_strip
182 # deselect all other strips
183 for i in context.selected_editable_sequences:
184 if i.name != newstrip.name:
185 i.select = False
187 # Update scene
188 context.scene.update()
189 else:
190 create_proxy_scripts(proxy_scripts_path, commands, strip.name)
192 return {'FINISHED'}
195 class CreateBIProxyOperator(Operator):
196 bl_idname = "sequencer.create_bi_proxy_operator"
197 bl_label = "Create proxy with Blender Internal"
198 bl_description = "Use BI system to create a proxy"
199 bl_options = {'REGISTER', 'UNDO'}
201 size: IntProperty(
202 name="Proxy Size",
203 default=1
206 @classmethod
207 def poll(self, context):
208 strip = functions.act_strip(context)
209 scn = context.scene
210 if scn and scn.sequence_editor and scn.sequence_editor.active_strip:
211 return strip.type in ('MOVIE')
212 else:
213 return False
215 def execute(self, context):
216 try:
217 strips = functions.get_selected_strips(context)
219 for strip in strips:
220 # deselect all other strips
221 for i in strips:
222 i.select = False
223 # select current strip
224 strip.select = True
225 if strip.type == "MOVIE":
226 setup_proxy(context, strip, self.size)
227 except Exception as e:
228 functions.error_handlers(
229 self,
230 "sequencer.create_bi_proxy_operator", e,
231 "Create proxy with blender internal"
233 return {"CANCELLED"}
235 # select all strips again
236 for strip in strips:
237 try:
238 strip.select = True
239 except ReferenceError:
240 pass
241 bpy.ops.sequencer.reload()
243 return {'FINISHED'}
246 class CreateProxyToolPanel(Panel):
247 bl_label = "Proxy Tools"
248 bl_idname = "OBJECT_PT_ProxyTool"
249 bl_space_type = 'SEQUENCE_EDITOR'
250 bl_region_type = 'UI'
252 @classmethod
253 def poll(self, context):
254 if context.space_data.view_type in {'SEQUENCER',
255 'SEQUENCER_PREVIEW'}:
256 strip = functions.act_strip(context)
257 scn = context.scene
258 preferences = context.preferences
259 prefs = preferences.addons[__package__].preferences
260 if scn and scn.sequence_editor and scn.sequence_editor.active_strip:
261 if prefs.use_proxy_tools:
262 return strip.type in ('MOVIE')
263 else:
264 return False
266 def draw_header(self, context):
267 layout = self.layout
268 layout.label(text="", icon="AUTO")
270 def draw(self, context):
272 preferences = context.preferences
273 prefs = preferences.addons[__package__].preferences
275 layout = self.layout
276 layout.prop(prefs, "use_internal_proxy", text="Use BI proxy builder")
278 strip = functions.act_strip(context)
280 if prefs.use_internal_proxy:
281 layout = self.layout
282 row = layout.row(align=True)
283 row.prop(prefs, "use_bi_custom_directory")
285 if prefs.use_bi_custom_directory:
286 row.prop(prefs, "proxy_dir", text="")
287 filename = strip.filepath.rpartition("/")[2].rpartition(".")[0]
288 layout.label(text="sample dir: //" + bpy.path.abspath(prefs.proxy_dir + filename))
290 layout = self.layout
291 col = layout.column()
292 col.label(text="Build JPEG quality")
293 col.prop(prefs, "quality")
295 if strip.type == 'MOVIE':
296 col = layout.column()
297 col.label(text="Use timecode index:")
299 col.prop(prefs, "timecode")
301 layout = self.layout
302 layout.label(text="Setup and create BI proxy:")
303 row = layout.row(align=True)
305 for i in range(4):
306 proxysuffix = proxy_qualities[i][1]
307 row.operator("sequencer.create_bi_proxy_operator",
308 text=proxysuffix).size = i + 1
310 layout = self.layout
311 layout.operator("sequencer.create_bi_proxy_operator",
312 text="Clear proxy sizes").size = 5
314 else:
315 layout = self.layout
316 layout.prop(prefs, "proxy_dir", text="Path for proxies")
318 layout = self.layout
319 layout.label(text="Create and import proxy from clip:")
320 row = layout.row(align=True)
322 layout = self.layout
323 layout.prop(prefs, "ffmpeg_command", text="command")
325 layout.label(text="{} = filename, with, height, fileoutput")
326 label = prefs.ffmpeg_command.format("filename", "with", "height", "fileoutput")
327 layout.label(label)
329 for i in range(4):
330 proxysuffix = proxy_qualities[i][1]
331 row.operator("sequencer.create_proxy_operator",
332 text=proxysuffix).size = i + 1
334 layout = self.layout
335 layout.prop(prefs, "proxy_scripts")
337 if prefs.proxy_scripts:
338 layout = self.layout
339 layout.prop(prefs, "proxy_scripts_path", text="Path for scripts")
341 layout = self.layout
342 box = layout.box()
343 box.prop(context.space_data, "proxy_render_size")
344 box.operator("sequencer.rebuild_proxy", text="Rebuild Proxies and TC")