diff --git a/biz/ffmpeg.py b/biz/ffmpeg.py
index 615f427..ee7d89f 100644
--- a/biz/ffmpeg.py
+++ b/biz/ffmpeg.py
@@ -30,7 +30,9 @@ def parse_ffmpeg_task(task_info, template_info):
                     continue
             sub_ffmpeg_task = FfmpegTask(source)
             sub_ffmpeg_task.annexb = True
+            sub_ffmpeg_task.ext_data = find_placeholder_params(part.get('source'), task_params) or {}
             sub_ffmpeg_task.frame_rate = template_info.get("frame_rate", 25)
+            sub_ffmpeg_task.center_cut = part.get("crop_mode", None)
             for effect in part.get('effects', []):
                 sub_ffmpeg_task.add_effect(effect)
             for lut in part.get('filters', []):
@@ -59,6 +61,19 @@ def parse_ffmpeg_task(task_info, template_info):
         return task
 
 
+def find_placeholder_params(source, task_params):
+    if source.startswith('PLACEHOLDER_'):
+        placeholder_id = source.replace('PLACEHOLDER_', '')
+        new_sources = task_params.get(placeholder_id, [])
+        if type(new_sources) is list:
+            if len(new_sources) == 0:
+                logger.debug("no video found for placeholder: " + placeholder_id)
+                return {}
+            else:
+                return new_sources[0]
+        return {}
+
+
 def parse_video(source, task_params, template_info):
     print(source)
     if source.startswith('PLACEHOLDER_'):
diff --git a/entity/ffmpeg.py b/entity/ffmpeg.py
index 3e0127d..cdb69c6 100644
--- a/entity/ffmpeg.py
+++ b/entity/ffmpeg.py
@@ -1,3 +1,4 @@
+import json
 import time
 import uuid
 
@@ -47,6 +48,7 @@ class FfmpegTask(object):
             _str += f', effects={self.effects}'
         if self.mute:
             _str += f', mute={self.mute}'
+        _str += f', center_cut={self.center_cut}'
         return _str + ')'
 
     def analyze_input_render_tasks(self):
@@ -170,11 +172,14 @@ class FfmpegTask(object):
                 elif isinstance(input_file, FfmpegTask):
                     input_args.append(input_file.get_output_file())
             if self.center_cut == 1:
-                pos_json = self.ext_data.get('posJson', {})
+                pos_json_str = self.ext_data.get('posJson', '{}')
+                pos_json = json.loads(pos_json_str)
                 _v_w = pos_json.get('imgWidth', 1)
                 _f_x = pos_json.get('ltX', 0)
-                _x = f'{float(_f_x/_v_w) :.5f}*iw'
-                filter_args.append(f"[{video_output_str}]crop=x={_x}:y=0:w=ih*ih/iw:h=ih[{video_output_str}]")
+                _f_x2 = pos_json.get('rbX', 0)
+                _x = f'{float((_f_x2 - _f_x)/(2 * _v_w)) :.4f}*iw'
+                filter_args.append(f"{video_output_str}crop=x={_x}:y=0:w=ih*ih/iw:h=ih[v_cut]")
+                video_output_str = "[v_cut]"
             for effect in self.effects:
                 if effect.startswith("cameraShot:"):
                     param = effect.split(":", 2)[1]
@@ -199,7 +204,7 @@ class FfmpegTask(object):
                     ...
                 ...
             for lut in self.luts:
-                filter_args.append(f"[{video_output_str}]lut3d=file={lut}[{video_output_str}]")
+                filter_args.append(f"{video_output_str}lut3d=file={lut}{video_output_str}")
             for overlay in self.overlays:
                 input_index = input_args.count("-i")
                 input_args.append("-i")
diff --git a/util/api.py b/util/api.py
index dff5846..073d524 100644
--- a/util/api.py
+++ b/util/api.py
@@ -90,7 +90,7 @@ def get_template_info(template_id):
             'updateTime': remote_template_info.get('updateTime', template_id),
             'scenic_name': remote_template_info.get('scenicName', '景区'),
             'name': remote_template_info.get('name', '模版'),
-            'video_size': '1920x1080',
+            'video_size': remote_template_info.get('resolution', '1920x1080'),
             'frame_rate': 25,
             'overall_duration': 30,
             'video_parts': [