1. osgb 倾斜摄影转 fbx/rvt/obj 的真实工程痛点
倾斜摄影模型在测绘、智慧城市、BIM 正向设计里最常见的交付格式就是 osgb。它本质是一套带 LOD 层级的瓦片目录,Data/Tile_+000_+000/Tile_+000_+000.osgb这种结构,配合metadata.xml描述坐标系和层级。问题在于:甲方要 fbx 进 3ds Max 做效果图,结构专业要 rvt 进 Revit 做碰撞检查,Web 端要 glb/gltf 做轻量化展示,而 osgb 本身既不是单文件、也不是通用交换格式,直接拖进任何编辑器都打不开。
我接触过的团队里,处理这件事通常有三条路。第一条是装 ContextCapture 或 Smart3D 重新导出,但原始工程文件往往已经丢了,只剩一堆 osgb 瓦片,重新空三成本极高。第二条是找各种桌面转换器,装完发现要么只支持单文件、要么批量时内存爆掉、要么导出的 glb 丢失贴图。第三条是写脚本调开源库,比如用 Python 的 py3dtiles 或 assimp 做中转,但 osgb 的解析库生态很碎,坐标系和纹理路径一处理不好就全乱。
真正的痛点不是"能不能转",而是"批量转的时候怎么保证完整性、怎么验证没丢东西"。一个 200 平方公里的倾斜摄影项目,osgb 瓦片动辄几万个,转完之后你不可能一个个打开看。所以需要一套可复制的链路:统一入口拿 Key、批量提交任务、用文件头和体积做机器可验证的比对。这篇就按这个思路走,把 osgb 到 fbx/rvt/obj/glb/gltf 的在线转换与查看串起来,重点放在可跟做的配置和验证动作上。
先说清楚适合谁:如果你手里有 osgb 瓦片目录、需要批量产出 fbx 或 glb 交付、又不想在每台机器上装一堆转换软件,那这套流程能省很多事。如果你只是偶尔转一两个模型,直接拖进在线查看器就够了,不必上批量链路。下面从统一 Key 的配置开始,一步步到验证。
2. TaoToken 统一 Key 前置配置与在线转换查看工具接入
把 TaoToken 理解成一个统一的模型调用入口就行:你不需要在每台机器、每个工具里分别填不同的地址和密钥,而是拿一个 Key、一个 Base URL,让转换任务提交、模型对话、coding 辅助都走同一套凭证。对倾斜摄影这种要批量跑任务的场景,统一 Key 最大的好处是脚本里只维护一份配置,换机器、换环境不用改代码。
先拿 Key。打开官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,注册后在控制台里创建 API Key。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,Key 列表页在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。创建时建议按项目命名,比如osgb-batch-convert,方便后面排查是哪个任务在调用。
Base URL 统一用 https://taotoken.net/api ,注意这个地址不加 UTM 参数,脚本里直接写死即可。模型 ID 按你实际要用的填,比如做格式转换任务编排时用claude-sonnet-4-5这类模型来生成转换脚本或校验逻辑,具体以控制台模型列表为准。三件套就是:Base URL =https://taotoken.net/api,API Key = 你创建的那串,Model ID = 控制台里选定的模型。
这里要区分两个概念。TaoToken 负责的是"调用与编排"这一层,也就是帮你统一凭证、统一请求入口;而 osgb 到 fbx/glb 的实际几何转换,是在你的转换工具或在线查看器里完成的。所以正确的心智模型是:TaoToken 管 Key 和请求,转换器管格式。别指望一个 Key 直接变出 fbx 文件,它是让批量脚本能稳定调起来的那根线。
配置方式有两种。一种是在 shell 里导出环境变量,适合临时跑:
export TAOTOKEN_BASE_URL="https://taotoken.net/api" export TAOTOKEN_API_KEY="sk-你的key" export TAOTOKEN_MODEL="claude-sonnet-4-5"另一种是写进项目配置文件,适合团队共享。如果你用 Claude Code 这类工具,配置会落在 settings 里;如果用 Codex,会落在auth.json。不管哪种,核心都是那三件套。下面一节给出可直接复制的配置片段。
3. 可复制的统一 Key 配置片段与批量转换任务提交
这一节给三段可直接复制的配置,覆盖不同工具形态。第一段是通用 JSON,适合大多数脚本读取:
{ "base_url": "https://taotoken.net/api", "api_key": "sk-替换成你的key", "model": "claude-sonnet-4-5", "timeout": 120, "max_retries": 3 }第二段是 TOML,适合 Python 项目用tomllib读取:
[taotoken] base_url = "https://taotoken.net/api" api_key = "sk-替换成你的key" model = "claude-sonnet-4-5" timeout = 120 max_retries = 3 [convert] osgb_root = "./Data" output_dir = "./output" target_formats = ["glb", "gltf", "obj", "fbx"]第三段是 Claude Code 的 settings 片段,路径按你本机实际位置放,通常是项目根目录下的.claude/settings.json:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-替换成你的key", "ANTHROPIC_MODEL": "claude-sonnet-4-5" } }如果你用 Codex,auth.json里对应写:
{ "base_url": "https://taotoken.net/api", "api_key": "sk-替换成你的key", "model": "claude-sonnet-4-5" }三件套在任何一种里都是 Base URL + Key + Model ID,缺一不可。配好之后,批量转换任务的提交逻辑可以这样写。核心思路是:遍历 osgb 瓦片目录,把每个瓦片路径和目标任务格式组装成请求,交给转换器处理,转换器本身可以是本地命令行工具,也可以是在线查看器的接口。
import os import json import requests with open("config.json", "r", encoding="utf-8") as f: cfg = json.load(f) BASE = cfg["base_url"] KEY = cfg["api_key"] MODEL = cfg["model"] headers = { "Authorization": f"Bearer {KEY}", "Content-Type": "application/json" } def collect_osgb(root): tiles = [] for dirpath, _, filenames in os.walk(root): for name in filenames: if name.lower().endswith(".osgb"): tiles.append(os.path.join(dirpath, name)) return tiles def submit_convert(tile_path, target_fmt): payload = { "model": MODEL, "input": tile_path, "target": target_fmt, "options": {"keep_texture": True, "merge_lod": False} } resp = requests.post(f"{BASE}/convert", headers=headers, json=payload, timeout=120) resp.raise_for_status() return resp.json() if __name__ == "__main__": tiles = collect_osgb("./Data") print(f"发现 {len(tiles)} 个 osgb 瓦片") for t in tiles[:5]: for fmt in ["glb", "obj"]: result = submit_convert(t, fmt) print(t, fmt, result.get("status"))这段脚本里,/convert是示意端点,实际以你使用的转换服务或在线查看器接口为准。重点在于:Key 和 Base URL 只从配置读一次,批量循环里复用,这样几万个瓦片跑下来不会因为凭证问题中断。提交时带上keep_texture和merge_lod这类选项,是因为倾斜摄影的纹理和 LOD 处理方式直接决定转换后模型能不能用。
在线查看这一环,可以用模型对话入口先确认模型本身没问题:https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 。把转换后的 glb 拖进查看器,看几何和贴图是否完整,再决定要不要批量跑全量。长期做编码和 Agent 编排的话,Coding Plan 入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,适合把上面这套脚本固化成可复用的流水线。
4. 验证请求与转换完整性:文件头与体积比对实操
转换跑完不等于转对了。倾斜摄影最容易出的问题是:几何在、纹理丢;或者 LOD 层级被压平导致模型变糊;或者坐标系偏移导致模型飞到天上去。所以必须有一套机器可验证的检查动作,不能靠肉眼。
第一个动作是文件头校验。不同格式的二进制头是固定的,读前几个字节就能判断文件是不是真的对应格式,而不是被错误命名的空壳。
def check_header(path): with open(path, "rb") as f: head = f.read(12) if head[:4] == b"glTF": return "glb" if head[:4] == b"Kayd": return "osgb" if head[:4] == b"ply\n" or head[:3] == b"ply": return "ply" if head[:2] == b"PK": return "可能为压缩包或 rvt 容器" return "unknown" for p in ["output/tile.glb", "output/tile.obj"]: print(p, check_header(p))glb 的头是glTF魔数,osgb 的头是Kayd,这两个最常用。obj 是文本格式,头几行通常是#注释或v顶点,读第一行判断即可。rvt 是 Revit 的专有容器,本质是复合文档,头是PK(zip 结构),所以看到PK不一定就是 rvt,还要结合扩展名和后续解析。
第二个动作是体积比对。同一个瓦片转成不同格式,体积应该在一个合理比例区间内。如果 glb 只有几 KB,而源 osgb 有几十 MB,基本可以判定纹理丢了或者几何被裁了。
import os def size_report(src, dst_list): src_size = os.path.getsize(src) print(f"源文件 {src}: {src_size/1024:.1f} KB") for d in dst_list: if os.path.exists(d): ds = os.path.getsize(d) ratio = ds / src_size flag = "正常" if 0.3 < ratio < 3.0 else "异常,需检查" print(f" {d}: {ds/1024:.1f} KB, 比例 {ratio:.2f} -> {flag}") size_report("Data/Tile_+000_+000.osgb", ["output/Tile_+000_+000.glb", "output/Tile_+000_+000.obj"])比例区间不是绝对的,glb 因为二进制打包通常比 obj 小,obj 带 mtl 和贴图目录时总体积可能更大。关键是看有没有数量级差异。我试过一批瓦片,glb 转出来只有 2 KB,一查是纹理路径没解析到,贴图全丢了,体积比对直接把这个坑暴露出来。
第三个动作是抽样渲染验证。从批量结果里随机抽 3 到 5 个,拖进在线查看器,确认贴图、朝向、层级都正常。这一步不能省,因为文件头和体积只能证明"文件结构对",证明不了"内容对"。抽样通过后,再跑全量校验脚本,把每个输出文件的头类型和体积比例都过一遍,生成一份报告。
python verify_batch.py --input ./output --report ./verify_report.csv报告里每行记录:源文件、目标文件、头类型、体积比例、是否通过。这样交付时附一份报告,甲方或下游团队能直接看到完整性依据,比口头说"转好了"靠谱得多。
5. 本篇常见报错排查:401、local proxy failed、reading choices、OAuth
批量跑转换时,报错基本集中在凭证和请求这两层。下面按真实遇到的错误逐个说。
401 Unauthorized最常见。原因通常是 Key 没填对、Key 前后带了空格、或者环境变量没生效。排查顺序:先确认echo $TAOTOKEN_API_KEY能打印出完整 Key;再确认请求头里是Authorization: Bearer sk-xxx而不是漏了Bearer;最后确认 Base URL 是https://taotoken.net/api而不是别的路径。如果用的是 Claude Code 的 settings,检查ANTHROPIC_API_KEY和ANTHROPIC_BASE_URL是否都写对了,只写一个会直接 401。
local proxy failed这类报错,通常出现在请求根本没发出去的时候。检查本机网络是否能正常访问https://taotoken.net/api,用curl -I https://taotoken.net/api看返回码。如果脚本里配了代理相关变量,确认没有残留的无效配置。这个错误和 Key 无关,是链路层的问题,先解决连通性再看凭证。
reading choices报错一般出现在解析响应的时候。意思是代码期望响应里有choices字段,但实际返回的结构不是这个形状。原因可能是请求体格式不对,比如把model写成了model_id,或者端点用错了。排查方法:把原始响应print(resp.text)打出来,看服务端到底返回了什么。如果是错误信息,按错误信息改;如果是空响应,检查请求方法是不是 POST、Content-Type 是不是application/json。
OAuth相关报错,多出现在用 Claude Code 或类似工具时,工具尝试走 OAuth 流程但配置里给的是 API Key。这时候要确认工具支持的是 Key 模式还是 OAuth 模式,两者不能混。用 Key 模式就把 OAuth 相关字段清掉,只留 Base URL、Key、Model ID 三件套。如果工具强制要 OAuth,那就按工具文档走 OAuth 配置,不要硬塞 Key。
还有一个隐蔽的坑:批量任务跑到一半开始报错,前面几百个都成功。这通常是触发了速率限制。解决办法是在脚本里加退避重试,max_retries设 3 次,每次间隔翻倍。上面配置片段里的max_retries就是干这个的。另外把批量任务分批提交,每批之间 sleep 几秒,比一次性打满要稳。
排查时记住一个原则:先看错误码,再看错误信息,最后看请求原文。401 看凭证,连接类错误看网络,解析类错误看响应结构,OAuth 看模式是否匹配。把这四类分开,定位速度会快很多。
6. 把 osgb 转换链路固化成可复用流程
走到这里,链路已经完整了:统一 Key 配置、批量提交、文件头与体积验证、报错排查。最后说几个把它固化成团队流程的实用点。
第一,把配置和脚本一起进版本库,但 Key 不要硬编码。用环境变量或本地config.local.json覆盖,.gitignore里排除掉含 Key 的文件。这样新人拉下来改一个 Key 就能跑。
第二,验证报告作为交付物的一部分。每次批量转换生成一份 CSV,记录每个文件的头类型和体积比例。下游团队拿到报告,能快速定位是哪个瓦片有问题,不用全量重跑。
第三,格式选择按用途定。Web 展示优先 glb,体积小、加载快;进 3ds Max 做效果图用 fbx;进 Revit 做 BIM 用 rvt,但 rvt 转换对坐标系要求高,建议先转 obj 或 glb 再导入;obj 适合做中间交换格式,兼容性最好但体积大。gltf 和 glb 的区别是前者文本、后者二进制,批量场景优先 glb。
第四,抽样验证不能省。文件头和体积是机器校验,抽样渲染是人工兜底,两者结合才能保证交付质量。抽 3 到 5 个,覆盖不同区域和不同 LOD 层级,比随机抽更有效。
需要接入文档和 Key 管理的,走 API Keys 页 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 和文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。验证单个模型效果用模型对话 https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 。要把这套批量转换和校验固化成长期跑的 Agent 流水线,用 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。Claude Code 接入参考 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude-code-anthropic&utm_campaign=rewrite 。
最后留一个实操建议:第一次跑全量前,先拿 10 个瓦片做小批量,把文件头、体积、抽样渲染三步都走一遍,确认脚本和配置没问题,再放开跑。倾斜摄影项目动辄几万瓦片,返工成本高,小批量验证这十分钟能省掉后面几小时的排查。