Files
workinf_Blender_Wasm/tools/web/build-webengine-ffmpeg.py
mes123456 f3e21c6b98
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer,
web workflow engine and protocol, tooling, docs and task records.
Large generated evidence, user-testing archives, build snapshots and
imported test assets remain untracked.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-10 11:18:01 +08:00

90 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""Build Blender-pinned FFmpeg audio libraries for the embedded Audaspace plugin."""
import argparse
import hashlib
import json
import os
from pathlib import Path
import shutil
import subprocess
import tarfile
import urllib.request
ROOT = Path(__file__).resolve().parents[2]
VERSION = "8.1"
SHA256 = "c07039598df7d64d3c8b42c4e25b1959fc908621c6f6c2946881133f3b27eda2"
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--source", type=Path)
parser.add_argument("--jobs", type=int, default=3)
args = parser.parse_args()
base = ROOT / "build_web_ffmpeg"
base.mkdir(exist_ok=True)
source = args.source.resolve() if args.source else base / f"ffmpeg-{VERSION}"
if not (source / "configure").is_file():
if args.source:
raise FileNotFoundError(source)
filename = f"ffmpeg-{VERSION}.tar.bz2"
caches = [base / filename, Path.home() / "working/packages" / filename,
Path.home() / "working/build_oiio_deps/downloads" / filename]
archive = next((path for path in caches if path.is_file()), caches[0])
if not archive.is_file():
partial = archive.with_suffix(".partial")
with urllib.request.urlopen(f"https://ffmpeg.org/releases/{filename}", timeout=60) as response, partial.open("wb") as out:
shutil.copyfileobj(response, out)
partial.replace(archive)
if hashlib.sha256(archive.read_bytes()).hexdigest() != SHA256:
raise RuntimeError("Blender-pinned FFmpeg archive digest mismatch")
with tarfile.open(archive) as package:
package.extractall(base, filter="data")
if (source / "RELEASE").read_text().strip() != VERSION:
raise RuntimeError("Expected Blender-pinned FFmpeg " + VERSION)
prefix = base / "install"
build = base / "build"
build.mkdir(exist_ok=True)
em = ROOT / ".emsdk/upstream/emscripten"
codecs = ROOT / "build_web_sndfile/install"
env = dict(os.environ)
env["PATH"] = str(em) + os.pathsep + env["PATH"]
env["PKG_CONFIG_LIBDIR"] = str(codecs / "lib/pkgconfig")
env["PKG_CONFIG_PATH"] = ""
command = [str(source / "configure"), f"--prefix={prefix}",
"--target-os=none", "--arch=wasm32", "--enable-cross-compile",
"--cc=" + str(em / "emcc"), "--cxx=" + str(em / "em++"),
"--ar=" + str(em / "emar"), "--ranlib=" + str(em / "emranlib"),
"--nm=" + str(em.parent / "bin/llvm-nm"),
f"--extra-cflags=-O2 -fPIC -I{codecs / 'include'}",
f"--extra-ldflags=-L{codecs / 'lib'}", "--disable-asm", "--disable-x86asm",
"--disable-pthreads", "--disable-w32threads", "--disable-os2threads",
"--disable-network", "--disable-autodetect", "--disable-everything",
"--disable-programs", "--disable-doc", "--disable-debug",
"--disable-avdevice", "--disable-avfilter", "--disable-swscale",
"--disable-shared", "--enable-static", "--enable-small",
"--enable-protocol=file", "--enable-libmp3lame", "--enable-libopus",
"--enable-libvorbis", "--pkg-config-flags=--static",
"--enable-encoder=aac,ac3,mp2,flac,libmp3lame,libopus,libvorbis,pcm_u8,pcm_s16le,pcm_s24le,pcm_s32le,pcm_f32le,pcm_f64le",
"--enable-decoder=aac,ac3,mp2,mp3,flac,opus,vorbis,pcm_u8,pcm_s16le,pcm_s24le,pcm_s32le,pcm_f32le,pcm_f64le",
"--enable-parser=aac,ac3,mpegaudio,flac,opus,vorbis",
"--enable-muxer=adts,ac3,mp2,mp3,flac,matroska,ogg,wav",
"--enable-demuxer=aac,ac3,mp3,flac,matroska,ogg,wav,mov",
"--enable-bsf=aac_adtstoasc,extract_extradata"]
settings = json.dumps([command, env["PKG_CONFIG_LIBDIR"]])
stamp = build / "web-configure.json"
if not stamp.is_file() or stamp.read_text() != settings:
subprocess.run(command, cwd=build, env=env, check=True)
stamp.write_text(settings)
subprocess.run(["make", f"-j{args.jobs}", "install"], cwd=build, env=env, check=True)
artifacts = {str(path.relative_to(ROOT)): hashlib.sha256(path.read_bytes()).hexdigest()
for path in sorted((prefix / "lib").glob("*.a"))}
(base / "build-manifest.json").write_text(json.dumps({
"version": VERSION, "source": str(source), "upstreamArchiveSha256": SHA256,
"configure": command, "artifacts": artifacts,
"validation": "NOT_RUN", "acceptance": "NOT_CLAIMED"}, indent=2) + "\n")
if __name__ == "__main__":
main()