本篇主要是介绍如何将渲染软件 Blender 创建成 BatchCompute 的 App,并通过此 App 提交 Blender 渲染作业。
Blender 是目前最流行的一款开源的跨平台全能三维动画制作软件,提供从建模、动画、材质、渲染、到音频处理、视频剪辑等一系列动画短片制作解决方案。 具体介绍可以看这里:https://www.blender.org/features/。
(2) 地域的选择 本篇例子所有阿里云服务都需要使用相同的地域。
本篇例子使用地域: 华南1(深圳)
(3) 准备OSS Bucket 请到OSS控制台 创建一个Bucket。 本篇例子假设创建的 bucket 名称为:blender-demo, 地域在华南1(深圳)。
注意: 使用批量计算时,地域需要和 OSS bucket 的地域相同。
注意: 实际操作时,需要将例子中的bucket 名称修改为您自己创建的真实的bucket名称。
FROM ubuntu:latest MAINTAINER your-name
RUN apt update
RUN apt autoclean
RUN apt install python python-pip curl pulseaudio blender -y
CMD ["/bin/bash"] (2) build docker build -t ubuntu-blender ./ 等待完成,然后使用下面的命令查看是否有 ubuntu-blender
docker images (3) check docker run -t ubuntu-blender blender -v 显示:
Blender 2.79 (sub 0)
记住此版本信息,下面要用到。
BatchCompute支持2种Registry:阿里云的 CR(Container Registry)和阿里云的OSS。
选择一种即可,推荐第一种: CR。
如何上传,请参考这2篇文档:
docker 镜像上传到CR
docker 镜像上传到OSS
假设已经上传到CR(地域:华南1-深圳),名称为: registry.cn-shenzhen.aliyuncs.com/batchcompute_test/blender:1.0
下面我们来创建一个 Blender 渲染 App。
(1) 开始创建 App 打开批量计算控制台: https://batchcompute.console.aliyun.com
1
填写基本信息 Docker 镜像名称,填写您已经上传到CR的镜像名称,如: registry.cn-shenzhen.aliyuncs.com/batchcompute_test/blender:1.0
2
运行时参数 只需修改 实例类型为 8核16GB规格,其他的默认即可。
3
(2) 命令行和参数配置 4
命令行填写: python -c "import os;import sys;sys.path.append('/home/scripts/'); from framer import parseFrames; frames=parseFrames('${frames}'); framestr=','.join(map(lambda x:str(x), frames)); s='blender -b /home/input/${scene_file_path} -o /home/output/result/${output_name_format} -F ${format} -f %s' % framestr; print('exec: %s' % s); os.system(s);" ${..} 都是变量,可以作为输入和输出参数。在使用此App提交作业的时候,传入的参数将替换掉这些变量。
参考文档 Blender 2.79 命令行参数
输入参数 注意: 实际操作时,需要将例子中的bucket 名称修改为您自己创建的真实的bucket名称。
名称 默认值 允许覆盖 本地目录绝对路径 备注 scripts_oss_folder oss://blender-demo/scripts/ 否 /home/scripts/ 输入oss目录路径,该路径将挂载到虚拟机的/home/scripts/,应该包含要渲染的 framer.py 文件, 如: oss://bucket/scripts/ input_oss_folder 是 /home/input/ 输入oss目录路径,该路径将挂载到虚拟机的/home/input/,应该包含要渲染的.blend文件, 如: oss://bucket/input/ scene_file_path 是 渲染场景文件的路径,相对于input_oss_folder的目录路径, 如:a.blend 或者 folder_name/a.blend frames 是 支持连续帧:”1-10”, 支持多帧(逗号隔开,无空格):”1,3,5-10” format PNG 是 渲染输出格式,支持: TGA,RAWTGA,JPEG,IRIS,IRIZ,AVIRAW,AVIJPEG,PNG,BMP output_name_format ####.png 是 输出文件名,#会被替代为帧序号,不足位补零。举例: test_###.png 变成 test_001.png,可以在前面加目录名: test/test_###.png 输出参数 名称 默认值 允许覆盖 本地目录绝对路径 备注 output_oss_folder 是 /home/output/ 输出oss目录路径, 如: oss://bucket/output/。 环境变量 环境变量可以不用配置, 直接提交即可。
5
(1) 准备工作 在提交作业前,还有一些准备工作。
手动上传分帧器 分帧器python代码(见附录),上传到您的OSS目录下,比如: oss://blender-demo/scripts/framer.py
手动上传blender场景文件 Blender 官网提供了好多 demo 文件: https://www.blender.org/download/demo-files/
本例子需要下载 2.79 版本(注意:要和镜像中安装的Blender版本相同。不同版本的可能渲染不出来)
6
素材下载后,解压得到目录: splash279/ 将整个目录上传到 oss://blender-demo/input/ 下面,即:oss://blender-demo/input/splash279/。
(2) 开始提交作业 7
实例类型要选大一点的,比如: 8核16GB。 实例数量本例子填 2 个。 (3) 参数配置 注意: 实际操作时,需要将例子中的 bucket 名称修改为您自己创建的真实的bucket名称。
8
输入: 参数 值 说明 input_oss_folder oss://blender-demo/input/ 场景文件所在OSS目录 scene_file_path splash279/splash279.blend 场景文件名 frames 1-4 渲染1到4帧 format PNG 渲染输出格式,默认即可 output_name_format ####.png 渲染输出文件名,默认即可 scripts_oss_folder 设置了默认值,且不允许覆盖,可以不用填。 输出: 参数 值 说明 input_oss_folder oss://blender-demo/output/ 输出OSS目录, 渲染结果图片将保存到此目录的 result/ 子目录下 Loggin(日志目录配置): 参数 值 说明 StdoutPath oss://blender-demo/log/ stdout日志输出到此 StderrPath oss://blender-demo/log/ stderr日志输出到此 填好后点击提交即可。
(2) 查看结果 oss://blender-demo/output/result/
10
(3) 渲染时长和实例规格参考 实例规格 节点数 渲染帧数 时长 ecs.sn1ne.2xlarge(8核16GB) 2 1-4 9-12分钟 ecs.sn1ne.4xlarge (16核/32GB) 2 1-4 4-6分钟 6. 附录 分帧器代码(python): framer.py:
#!/usr/bin/python
import os import math import sys import re NOTHING_TO_DO = 'Nothing to do, exit' def _calcRange(a,b, id, step): start = min(id * step + a, b) end = min((id+1) * step + a-1, b) return (start, end) def _parseContinuedFrames(render_frames, total_nodes, id=None, return_type='list'): ''' 解析连续帧, 如: 1-10 ''' [a,b]=render_frames.split('-') a=int(a) b=int(b) #print(a,b) step = int(math.ceil((b-a+1)*1.0/total_nodes)) #print('step:', step) mod = (b-a+1) % total_nodes #print('mod:', mod) if mod==0 or id < mod: (start, end) = _calcRange(a,b, id, step) #print('--->',start, end) return (start, end) if return_type!='list' else range(start, end+1) else: a1 = step * mod + a #print('less', a1, b, id) (start, end) = _calcRange(a1 ,b, id-mod, step-1) #print('--->',start, end) return (start, end) if return_type!='list' else range(start, end+1) def _parseIntermittentFrames(render_frames, total_nodes, id=None): ''' 解析不连续帧, 如: 1,3,8-10,21 ''' a1=render_frames.split(',') a2=[] for n in a1: a=n.split('-') a2.append(range(int(a[0]),int(a[1])+1) if len(a)==2 else [int(a[0])]) a3=[] for n in a2: a3=a3+n #print('a3',a3) step = int(math.ceil(len(a3)*1.0/total_nodes)) #print('step',step) mod = len(a3) % total_nodes #print('mod:', mod) if mod==0 or id < mod: (start, end) = _calcRange(0, len(a3)-1, id, step) #print(start, end) a4= a3[start: end+1] #print('--->', a4) return a4 else: #print('less', step * mod , len(a3)-1, id) (start, end) = _calcRange( step * mod ,len(a3)-1, id-mod, step-1) if start > len(a3)-1: print(NOTHING_TO_DO) sys.exit(0) #print(start, end) a4= a3[start: end+1] #print('--->', a4) return a4 def parseFrames(render_frames, return_type='list', id=None, total_nodes=None): ''' @param render_frames {string}: 需要渲染的总帧数列表范围,可以用"-"表示范围,不连续的帧可以使用","隔开, 如: 1,3,5-10 @param return_type {string}: 取值范围[list,range]。 list样例: [1,2,3], range样例: (1,3)。 注意: render_frames包含","时有效,强制为list。 @param id, 节点ID,从0开始。 正式环境不要填写,将从环境变量 BATCH_COMPUTE_DAG_INSTANCE_ID 中取得。 @param total_nodes, 总共的节点个数。正式环境不要填写,将从环境变量 BATCH_COMPUTE_DAG_INSTANCE_COUNT 中取得。 ''' if id==None: id=os.environ['BATCH_COMPUTE_DAG_INSTANCE_ID'] if type(id)==str: id = int(id) if total_nodes==None: total_nodes = os.environ['BATCH_COMPUTE_DAG_INSTANCE_COUNT'] if type(total_nodes)==str: total_nodes = int(total_nodes) if re.match(r'^(\d+)-(\d+)$',render_frames): # 1-2 # continued frames return _parseContinuedFrames(render_frames, total_nodes, id, return_type) else: # intermittent frames return _parseIntermittentFrames(render_frames, total_nodes, id)
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。