From ca93dd05724a5701b99a9710fe9a89f77cf60ab5 Mon Sep 17 00:00:00 2001
From: fdyuandong
Date: Thu, 17 Apr 2025 23:14:24 +0800
Subject: [PATCH] feat: Initial commit
---
.gitignore | 18 +
LICENSE | 201 +++++
README.md | 103 +++
app_lam_audio2exp.py | 271 +++++++
assets/images/logo.jpeg | Bin 0 -> 36452 bytes
assets/images/snapshot.png | Bin 0 -> 2126974 bytes
assets/images/teaser.jpg | Bin 0 -> 669222 bytes
configs/lam_audio2exp_config.py | 92 +++
configs/lam_audio2exp_config_streaming.py | 92 +++
configs/wav2vec2_config.json | 77 ++
engines/__init__.py | 0
engines/defaults.py | 147 ++++
engines/hooks/__init__.py | 5 +
engines/hooks/builder.py | 15 +
engines/hooks/default.py | 29 +
engines/hooks/evaluator.py | 577 ++++++++++++++
engines/hooks/misc.py | 460 +++++++++++
engines/infer.py | 285 +++++++
engines/launch.py | 135 ++++
engines/train.py | 299 +++++++
inference.py | 48 ++
inference_streaming_audio.py | 60 ++
models/__init__.py | 7 +
models/builder.py | 13 +
models/default.py | 25 +
models/encoder/wav2vec.py | 248 ++++++
models/encoder/wavlm.py | 87 ++
models/losses/__init__.py | 4 +
models/losses/builder.py | 28 +
models/losses/lovasz.py | 253 ++++++
models/losses/misc.py | 241 ++++++
models/network.py | 646 +++++++++++++++
models/utils.py | 752 ++++++++++++++++++
requirements.txt | 10 +
scripts/install/install_cu118.sh | 9 +
scripts/install/install_cu121.sh | 9 +
utils/__init__.py | 0
utils/cache.py | 53 ++
utils/comm.py | 192 +++++
utils/config.py | 696 ++++++++++++++++
utils/env.py | 33 +
utils/events.py | 585 ++++++++++++++
utils/logger.py | 167 ++++
utils/misc.py | 156 ++++
utils/optimizer.py | 52 ++
utils/path.py | 105 +++
utils/registry.py | 318 ++++++++
utils/scheduler.py | 144 ++++
utils/timer.py | 71 ++
utils/visualization.py | 86 ++
...dio_gaussian_render-0.0.2-py3-none-any.whl | Bin 0 -> 1506149 bytes
51 files changed, 7904 insertions(+)
create mode 100644 .gitignore
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 app_lam_audio2exp.py
create mode 100644 assets/images/logo.jpeg
create mode 100644 assets/images/snapshot.png
create mode 100644 assets/images/teaser.jpg
create mode 100644 configs/lam_audio2exp_config.py
create mode 100644 configs/lam_audio2exp_config_streaming.py
create mode 100644 configs/wav2vec2_config.json
create mode 100644 engines/__init__.py
create mode 100644 engines/defaults.py
create mode 100644 engines/hooks/__init__.py
create mode 100644 engines/hooks/builder.py
create mode 100644 engines/hooks/default.py
create mode 100644 engines/hooks/evaluator.py
create mode 100644 engines/hooks/misc.py
create mode 100644 engines/infer.py
create mode 100644 engines/launch.py
create mode 100644 engines/train.py
create mode 100644 inference.py
create mode 100644 inference_streaming_audio.py
create mode 100644 models/__init__.py
create mode 100644 models/builder.py
create mode 100644 models/default.py
create mode 100644 models/encoder/wav2vec.py
create mode 100644 models/encoder/wavlm.py
create mode 100644 models/losses/__init__.py
create mode 100644 models/losses/builder.py
create mode 100644 models/losses/lovasz.py
create mode 100644 models/losses/misc.py
create mode 100644 models/network.py
create mode 100644 models/utils.py
create mode 100644 requirements.txt
create mode 100644 scripts/install/install_cu118.sh
create mode 100644 scripts/install/install_cu121.sh
create mode 100644 utils/__init__.py
create mode 100644 utils/cache.py
create mode 100644 utils/comm.py
create mode 100644 utils/config.py
create mode 100644 utils/env.py
create mode 100644 utils/events.py
create mode 100644 utils/logger.py
create mode 100644 utils/misc.py
create mode 100644 utils/optimizer.py
create mode 100644 utils/path.py
create mode 100644 utils/registry.py
create mode 100644 utils/scheduler.py
create mode 100644 utils/timer.py
create mode 100644 utils/visualization.py
create mode 100644 wheels/gradio_gaussian_render-0.0.2-py3-none-any.whl
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..73c532f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+image/
+__pycache__
+**/build/
+**/*.egg-info/
+**/dist/
+*.so
+exp
+weights
+data
+log
+outputs/
+.vscode
+.idea
+*/.DS_Store
+TEMP/
+pretrained/
+**/*.out
+Dockerfile
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..f49a4e1
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7636ef6
--- /dev/null
+++ b/README.md
@@ -0,0 +1,103 @@
+# LAM-A2E: Audio to Expression
+
+[](https://aigc3d.github.io/projects/LAM/)
+[](https://www.apache.org/licenses/LICENSE-2.0)
+
+#### This project leverages audio input to generate ARKit blendshapes-driven facial expressions in ⚡real-time⚡, powering ultra-realistic 3D avatars generated by [LAM](https://github.com/aigc3d/LAM).
+
+## Demo
+
+
+
+
+
+## 📢 News
+
+
+### To do list
+- [ ] Release Huggingface space.
+- [ ] Release Modelscope space.
+- [ ] Release the LAM-A2E model based on the Flame expression.
+- [ ] Release Interactive Chatting Avatar SDK with [OpenAvatarChat](https://github.com/HumanAIGC-Engineering/OpenAvatarChat), including LLM, ASR, TTS, LAM-Avatars.
+
+
+
+## 🚀 Get Started
+### Environment Setup
+```bash
+git clone git@github.com:aigc3d/LAM_Audio2Expression.git
+cd LAM_Audio2Expression
+# Install with Cuda 12.1
+sh ./scripts/install/install_cu121.sh
+# Or Install with Cuda 11.8
+sh ./scripts/install/install_cu118.sh
+```
+
+
+### Download
+
+```
+# HuggingFace download
+# Download Assets and Model Weights
+huggingface-cli download 3DAIGC/LAM_audio2exp --local-dir ./
+tar -xzvf LAM_audio2exp_assets.tar && rm -f LAM_audio2exp_assets.tar
+tar -xzvf LAM_audio2exp_streaming.tar && rm -f LAM_audio2exp_streaming.tar
+
+
+# Or OSS Download (In case of HuggingFace download failing)
+# Download Assets
+wget https://virutalbuy-public.oss-cn-hangzhou.aliyuncs.com/share/aigc3d/data/LAM/LAM_audio2exp_assets.tar
+tar -xzvf LAM_audio2exp_assets.tar && rm -f LAM_audio2exp_assets.tar
+# Download Model Weights
+wget https://virutalbuy-public.oss-cn-hangzhou.aliyuncs.com/share/aigc3d/data/LAM/LAM_audio2exp_streaming.tar
+tar -xzvf LAM_audio2exp_streaming.tar && rm -f LAM_audio2exp_streaming.tar
+```
+
+
+### Quick Start Guide
+#### Using Gradio Interface:
+We provide a simple Gradio demo with **WebGLGL Render**, and you can get rendering results by uploading audio in seconds.
+
+
+
+
+
+```
+python app_lam_audio2exp.py
+```
+
+### Inference
+```bash
+# example: python inference.py --config-file configs/lam_audio2exp_config_streaming.py --options save_path=exp/audio2exp weight=pretrained_models/lam_audio2exp_streaming.tar audio_input=./assets/sample_audio/BarackObama_english.wav
+python inference.py --config-file ${CONFIG_PATH} --options save_path=${SAVE_PATH} weight=${CHECKPOINT_PATH} audio_input=${AUDIO_INPUT}
+```
+
+### Acknowledgement
+This work is built on many amazing research works and open-source projects:
+- [FLAME](https://flame.is.tue.mpg.de)
+- [FaceFormer](https://github.com/EvelynFan/FaceFormer)
+- [Meshtalk](https://github.com/facebookresearch/meshtalk)
+- [Unitalker](https://github.com/X-niper/UniTalker)
+- [Pointcept](https://github.com/Pointcept/Pointcept)
+
+Thanks for their excellent works and great contribution.
+
+
+### Related Works
+Welcome to follow our other interesting works:
+- [LAM](https://github.com/aigc3d/LAM)
+- [LHM](https://github.com/aigc3d/LHM)
+
+
+### Citation
+```
+@inproceedings{he2025LAM,
+ title={LAM: Large Avatar Model for One-shot Animatable Gaussian Head},
+ author={
+ Yisheng He and Xiaodong Gu and Xiaodan Ye and Chao Xu and Zhengyi Zhao and Yuan Dong and Weihao Yuan and Zilong Dong and Liefeng Bo
+ },
+ booktitle={arXiv preprint arXiv:2502.17796},
+ year={2025}
+}
+```
diff --git a/app_lam_audio2exp.py b/app_lam_audio2exp.py
new file mode 100644
index 0000000..96ce483
--- /dev/null
+++ b/app_lam_audio2exp.py
@@ -0,0 +1,271 @@
+"""
+Copyright 2024-2025 The Alibaba 3DAIGC Team Authors. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+import os
+import base64
+
+import gradio as gr
+import argparse
+from omegaconf import OmegaConf
+from gradio_gaussian_render import gaussian_render
+
+from engines.defaults import (
+ default_argument_parser,
+ default_config_parser,
+ default_setup,
+)
+from engines.infer import INFER
+from pathlib import Path
+
+try:
+ import spaces
+except:
+ pass
+
+h5_rendering = True
+
+
+def assert_input_image(input_image):
+ if input_image is None:
+ raise gr.Error('No image selected or uploaded!')
+
+
+def prepare_working_dir():
+ import tempfile
+ working_dir = tempfile.TemporaryDirectory()
+ return working_dir
+
+def get_image_base64(path):
+ with open(path, 'rb') as image_file:
+ encoded_string = base64.b64encode(image_file.read()).decode()
+ return f'data:image/png;base64,{encoded_string}'
+
+
+def doRender():
+ print('H5 rendering ....')
+
+def parse_configs():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--config", type=str)
+ parser.add_argument("--infer", type=str)
+ args, unknown = parser.parse_known_args()
+
+ cfg = OmegaConf.create()
+ cli_cfg = OmegaConf.from_cli(unknown)
+
+ # parse from ENV
+ if os.environ.get("APP_INFER") is not None:
+ args.infer = os.environ.get("APP_INFER")
+ if os.environ.get("APP_MODEL_NAME") is not None:
+ cli_cfg.model_name = os.environ.get("APP_MODEL_NAME")
+
+ args.config = args.infer if args.config is None else args.config
+
+ if args.config is not None:
+ cfg_train = OmegaConf.load(args.config)
+ cfg.source_size = cfg_train.dataset.source_image_res
+ try:
+ cfg.src_head_size = cfg_train.dataset.src_head_size
+ except:
+ cfg.src_head_size = 112
+ cfg.render_size = cfg_train.dataset.render_image.high
+ _relative_path = os.path.join(
+ cfg_train.experiment.parent,
+ cfg_train.experiment.child,
+ os.path.basename(cli_cfg.model_name).split("_")[-1],
+ )
+
+ cfg.save_tmp_dump = os.path.join("exps", "save_tmp", _relative_path)
+ cfg.image_dump = os.path.join("exps", "images", _relative_path)
+ cfg.video_dump = os.path.join("exps", "videos", _relative_path) # output path
+
+ if args.infer is not None:
+ cfg_infer = OmegaConf.load(args.infer)
+ cfg.merge_with(cfg_infer)
+ cfg.setdefault(
+ "save_tmp_dump", os.path.join("exps", cli_cfg.model_name, "save_tmp")
+ )
+ cfg.setdefault("image_dump", os.path.join("exps", cli_cfg.model_name, "images"))
+ cfg.setdefault(
+ "video_dump", os.path.join("dumps", cli_cfg.model_name, "videos")
+ )
+ cfg.setdefault("mesh_dump", os.path.join("dumps", cli_cfg.model_name, "meshes"))
+
+ cfg.motion_video_read_fps = 30
+ cfg.merge_with(cli_cfg)
+
+ cfg.setdefault("logger", "INFO")
+
+ assert cfg.model_name is not None, "model_name is required"
+
+ return cfg, cfg_train
+
+
+def create_zip_archive(output_zip='assets/arkitWithBSData.zip', base_dir=""):
+ import os
+ if (os.path.exists(output_zip)):
+ os.remove(output_zip)
+ print(f"Reomve previous file: {output_zip}")
+ run_command = 'zip -r '+output_zip+' '+base_dir
+ os.system(run_command)
+ # check file
+ if(os.path.exists(output_zip)):
+ print(f"Archive created successfully: {output_zip}")
+ else:
+ raise ValueError(f"Archive created failed: {output_zip}")
+
+
+def demo_lam_audio2exp(infer, cfg):
+ def core_fn(image_path: str, audio_params, working_dir):
+
+ base_id = os.path.basename(image_path).split(".")[0]
+
+ # set input audio
+ cfg.audio_input = audio_params
+ cfg.save_json_path = os.path.join("./assets/sample_lam", base_id, 'arkitWithBSData', 'bsData.json')
+ infer.infer()
+
+ create_zip_archive(output_zip='./assets/arkitWithBSData.zip', base_dir=os.path.join("./assets/sample_lam", base_id))
+
+ return
+
+ with gr.Blocks(analytics_enabled=False) as demo:
+ logo_url = './assets/images/logo.jpeg'
+ logo_base64 = get_image_base64(logo_url)
+ gr.HTML(f"""
+
+
+
LAM-A2E: Audio to Expression
+
+
+ """)
+
+ gr.HTML(
+ """ Notes: This project leverages audio input to generate ARKit blendshapes-driven facial expressions in ⚡real-time⚡, powering ultra-realistic 3D avatars generated by LAM.
"""
+ )
+
+ # DISPLAY
+ with gr.Row():
+ with gr.Column(variant='panel', scale=1):
+ with gr.Tabs(elem_id='lam_input_image'):
+ with gr.TabItem('Input Image'):
+ with gr.Row():
+ input_image = gr.Image(label='Input Image',
+ image_mode='RGB',
+ height=480,
+ width=270,
+ sources='upload',
+ type='filepath', # 'numpy',
+ elem_id='content_image')
+ # EXAMPLES
+ with gr.Row():
+ examples = [
+ ['assets/sample_input/barbara.jpg'],
+ ['assets/sample_input/status.png'],
+ ['assets/sample_input/james.png'],
+ ['assets/sample_input/vfhq_case1.png'],
+ ]
+ gr.Examples(
+ examples=examples,
+ inputs=[input_image],
+ examples_per_page=20,
+ )
+
+ with gr.Column():
+ with gr.Tabs(elem_id='lam_input_audio'):
+ with gr.TabItem('Input Audio'):
+ with gr.Row():
+ audio_input = gr.Audio(label='Input Audio',
+ type='filepath',
+ waveform_options={
+ 'sample_rate': 16000,
+ 'waveform_progress_color': '#4682b4'
+ },
+ elem_id='content_audio')
+
+ examples = [
+ ['assets/sample_audio/Nangyanwen_chinese.wav'],
+ ['assets/sample_audio/LiBai_TTS_chinese.wav'],
+ ['assets/sample_audio/LinJing_TTS_chinese.wav'],
+ ['assets/sample_audio/BarackObama_english.wav'],
+ ['assets/sample_audio/HillaryClinton_english.wav'],
+ ['assets/sample_audio/XitongShi_japanese.wav'],
+ ['assets/sample_audio/FangXiao_japanese.wav'],
+ ]
+ gr.Examples(
+ examples=examples,
+ inputs=[audio_input],
+ examples_per_page=10,
+ )
+
+ # SETTING
+ with gr.Row():
+ with gr.Column(variant='panel', scale=1):
+ submit = gr.Button('Generate',
+ elem_id='lam_generate',
+ variant='primary')
+
+ if h5_rendering:
+ gr.set_static_paths(Path.cwd().absolute() / "assets/")
+ assetPrefix = 'gradio_api/file=assets/'
+ with gr.Row():
+ gs = gaussian_render(width=380, height=680, assets=assetPrefix + 'arkitWithBSData.zip')
+
+ working_dir = gr.State()
+ submit.click(
+ fn=assert_input_image,
+ inputs=[input_image],
+ queue=False,
+ ).success(
+ fn=prepare_working_dir,
+ outputs=[working_dir],
+ queue=False,
+ ).success(
+ fn=core_fn,
+ inputs=[input_image, audio_input,
+ working_dir], # video_params refer to smpl dir
+ outputs=[],
+ queue=False,
+ ).success(
+ doRender, js='''() => window.start()'''
+ )
+
+ demo.queue()
+ demo.launch()
+
+
+
+def launch_gradio_app():
+ os.environ.update({
+ 'APP_ENABLED': '1',
+ 'APP_MODEL_NAME':'',
+ 'APP_INFER': 'configs/lam_audio2exp_streaming_config.py',
+ 'APP_TYPE': 'infer.audio2exp',
+ 'NUMBA_THREADING_LAYER': 'omp',
+ })
+
+ args = default_argument_parser().parse_args()
+ args.config_file = 'configs/lam_audio2exp_config_streaming.py'
+ cfg = default_config_parser(args.config_file, args.options)
+ cfg = default_setup(cfg)
+
+ cfg.ex_vol = True
+ infer = INFER.build(dict(type=cfg.infer.type, cfg=cfg))
+
+ demo_lam_audio2exp(infer, cfg)
+
+
+if __name__ == '__main__':
+ launch_gradio_app()
diff --git a/assets/images/logo.jpeg b/assets/images/logo.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..6fa8d782014c5a0a78cf953e7b08bbfbc20b9aa1
GIT binary patch
literal 36452
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