diff --git a/.env b/.env
index 59de584..313cda5 100644
--- a/.env
+++ b/.env
@@ -1,4 +1,4 @@
 TEMPLATE_DIR=template/
-API_ENDPOINT=http://127.0.0.1:8030/task/v1/sync
+API_ENDPOINT=http://127.0.0.1:8030/task/v1
 ACCESS_KEY=TEST_ACCESS_KEY
 TEMP_DIR=tmp/
\ No newline at end of file
diff --git a/entity/ffmpeg.py b/entity/ffmpeg.py
index 62234f5..b8f6f91 100644
--- a/entity/ffmpeg.py
+++ b/entity/ffmpeg.py
@@ -170,7 +170,7 @@ class FfmpegTask(object):
                 output_args.append(audio_output_str)
             return args + input_args + ["-filter_complex", ";".join(filter_args)] + output_args + [self.get_output_file()]
         elif self.task_type == 'concat':
-            input_args = []
+            input_args = ["-hwaccel qsv"]
             output_args = []
             filter_args = []
             video_output_str = "[0:v]"
diff --git a/template/__init__.py b/template/__init__.py
index 7d9b610..ec3fc6e 100644
--- a/template/__init__.py
+++ b/template/__init__.py
@@ -2,6 +2,8 @@ import json
 import os
 import logging
 
+from util import api, oss
+
 TEMPLATES = {}
 logger = logging.getLogger("template")
 
@@ -71,8 +73,42 @@ def get_template_def(template_id):
     return TEMPLATES.get(template_id)
 
 def download_template(template_id):
-    logger.info(f"下载模板:{template_id}")
-    ...
+    template_info = api.get_template_info(template_id)
+    # download template assets
+    overall_template = template_info['overall_template']
+    video_parts = template_info['video_parts']
+    def _download_assets(_template):
+        if 'source' in _template:
+            if str(_template['source']).startswith("http"):
+                _, _fn = os.path.split(_template['source'])
+                oss.download_from_oss(_template['source'], os.path.join(template_info['local_path'], _fn))
+                _template['source'] = _fn
+        if 'overlays' in _template:
+            for i in range(len(_template['overlays'])):
+                overlay = _template['overlays'][i]
+                if str(overlay).startswith("http"):
+                    _, _fn = os.path.split(overlay)
+                    oss.download_from_oss(overlay, os.path.join(template_info['local_path'], _fn))
+                    _template['overlays'][i] = _fn
+        if 'luts' in _template:
+            for i in range(len(_template['luts'])):
+                lut = _template['luts'][i]
+                if str(lut).startswith("http"):
+                    _, _fn = os.path.split(lut)
+                    oss.download_from_oss(lut, os.path.join(template_info['local_path'], _fn))
+                    _template['luts'][i] = _fn
+        if 'audios' in _template:
+            for i in range(len(_template['audios'])):
+                if str(_template['audios'][i]).startswith("http"):
+                    _, _fn = os.path.split(_template['audios'][i])
+                    oss.download_from_oss(_template['audios'][i], os.path.join(template_info['local_path'], _fn))
+                    _template['audios'][i] = _fn
+    _download_assets(overall_template)
+    for video_part in video_parts:
+        _download_assets(video_part)
+    with open(os.path.join(template_info['local_path'], 'template.json'), 'w', encoding='utf-8') as f:
+        json.dump(template_info, f)
+    load_template(template_id, template_info['local_path'])
 
 
 def analyze_template(template_id):
diff --git a/util/api.py b/util/api.py
index 62b49f1..9824e02 100644
--- a/util/api.py
+++ b/util/api.py
@@ -8,13 +8,14 @@ import util.system
 session = requests.Session()
 logger = logging.getLogger(__name__)
 
+
 def sync_center():
     """
     通过接口获取任务
     :return: 任务列表
     """
     try:
-        response = session.post(os.getenv('API_ENDPOINT'), json={
+        response = session.post(os.getenv('API_ENDPOINT') + "/sync", json={
             'accessKey': os.getenv('ACCESS_KEY'),
             'clientStatus': util.system.get_sys_info()
         }, timeout=10)
@@ -39,39 +40,59 @@ def get_template_info(template_id):
     :type template_id: str
     :return: 模板信息
     """
+    try:
+        response = session.post('{0}/template/{1}'.format(os.getenv('API_ENDPOINT'), template_id), json={
+            'accessKey': os.getenv('ACCESS_KEY'),
+            'clientStatus': util.system.get_sys_info()
+        }, timeout=10)
+    except requests.RequestException as e:
+        logger.error("请求失败!", e)
+        return None
+    data = response.json()
+    remote_template_info = data.get('data', {})
+    logger.debug("获取模板信息结果:【%s】", remote_template_info)
     template = {
         'id': template_id,
-        'name': '模板名称',
-        'description': '模板描述',
+        'scenic_name': remote_template_info.get('scenicName', '景区'),
+        'name': remote_template_info.get('name', '模版'),
         'video_size': '1920x1080',
         'frame_rate': 30,
         'overall_duration': 30,
         'video_parts': [
-            {
-                'source': './template/test_template/1.mp4',
-                'mute': True,
-            },
-            {
-                'source': 'PLACEHOLDER_CAM_ID',
-                'mute': True,
-                'overlays': [
-                    './template/test_template/2.mov'
-                ],
-                'luts': [
-                    './template/test_template/cube.cube'
-                ]
-            },
-            {
-                'source': './template/test_template/3.mp4',
-                'mute': True,
-            }
-        ],
-        'overall_template': {
-            'source': None,
-            'mute': False,
-            'audios': [
-                './template/test_template/bgm.acc'
-            ]
-        },
+
+        ]
     }
-    return template
\ No newline at end of file
+
+    def _template_normalizer(template_info):
+        _template = {}
+        _placeholder_type = template_info.get('isPlaceholder', -1)
+        if _placeholder_type == 0:
+            # 固定视频
+            _template['source'] = template_info.get('sourceUrl', '')
+        elif _placeholder_type == 1:
+            # 占位符
+            _template['source'] = "PLACEHOLDER_" + template_info.get('sourceUrl', '')
+            _template['mute'] = template_info.get('mute', True)
+        else:
+            _template['source'] = None
+        _overlays = template_info.get('overlays', '')
+        if _overlays:
+            _template['overlays'] = _overlays.split(",")
+        _audios = template_info.get('audios', '')
+        if _audios:
+            _template['audios'] = _audios.split(",")
+        _luts = template_info.get('luts', '')
+        if _luts:
+            _template['luts'] = _luts.split(",")
+        return _template
+
+    # outer template definition
+    overall_template = _template_normalizer(remote_template_info)
+    template['overall_template'] = overall_template
+    # inter template definition
+    inter_template_list = remote_template_info.get('children', [])
+    for children_template in inter_template_list:
+        parts = _template_normalizer(children_template)
+        template['video_parts'].append(parts)
+    template['local_path'] = os.path.join(os.getenv('TEMPLATE_DIR'), str(template_id))
+    return template
diff --git a/util/oss.py b/util/oss.py
index fac1178..9cf4733 100644
--- a/util/oss.py
+++ b/util/oss.py
@@ -1,7 +1,9 @@
+import os
+
 import requests
 
 
-def upload_to_oss_use_signed_url(url, file_path):
+def upload_to_oss(url, file_path):
     """
     使用签名URL上传文件到OSS
     :param str url: 签名URL
@@ -15,3 +17,22 @@ def upload_to_oss_use_signed_url(url, file_path):
         except Exception as e:
             print(e)
             return False
+
+def download_from_oss(url, file_path):
+    """
+    使用签名URL下载文件到OSS
+    :param str url: 签名URL
+    :param Union[LiteralString, str, bytes] file_path: 文件路径
+    :return bool: 是否成功
+    """
+    file_dir, file_name = os.path.split(file_path)
+    if not os.path.exists(file_dir):
+        os.makedirs(file_dir)
+    try:
+        response = requests.get(url)
+        with open(file_path, 'wb') as f:
+            f.write(response.content)
+        return True
+    except Exception as e:
+        print(e)
+        return False
diff --git a/util/system.py b/util/system.py
index de6fda0..7596d53 100644
--- a/util/system.py
+++ b/util/system.py
@@ -1,5 +1,7 @@
 import os
 import platform
+from datetime import datetime
+
 import psutil
 from constant import SUPPORT_FEATURE, SOFTWARE_VERSION
 
@@ -10,6 +12,7 @@ def get_sys_info():
     """
     info = {
         'version': SOFTWARE_VERSION,
+        'client_datetime': datetime.now().isoformat(),
         'platform': platform.system(),
         'runtime_version': 'Python ' + platform.python_version(),
         'cpu_count': os.cpu_count(),