PythonIDE Docs
中文
简体中文

media_composer

视频合并、配音与导出。

视频合成与导出:按顺序拼接视频、为视频替换/添加音轨、转码导出 MP4。

边界:基于 AVFoundation,操作可能耗时较长(阻塞脚本数秒到两分钟)。输入/输出路径须为 App 可访问的本地文件;合成放在按钮回调,不要在 body() 中自动执行。素材可先由 video_recorderphotos 获得。

#模块概览

说明
导入import media_composer
适合做什么多段录像拼接、替换背景音、统一导出 MP4
调用时机用户确认后调用;显示进度/状态中
推荐顺序确认源文件存在 → merge_videos / merge_audio / export → 校验输出路径
输出格式当前 Bridge 导出为 .mp4

#快速开始

下面脚本检查素材是否存在,再合并导出:

python
import os
import media_composer

clip = os.path.join(os.path.expanduser("~/Documents"), "clip1.mov")
out = os.path.join(os.path.expanduser("~/Documents"), "merged.mp4")

if not os.path.exists(clip):
    print("请先把视频放到:", clip)
else:
    try:
        path = media_composer.merge_videos([clip], out)
        print("已导出:", path)
    except media_composer.MediaComposerError as exc:
        print("合成失败:", exc, f"code={exc.code}")

为视频替换音轨:

python
import media_composer

media_composer.merge_audio("video.mov", "audio.m4a", "output.mp4")

#AppUI 示例

合成放在按钮回调;先检查文件是否存在再执行。

python
import appui
import os
import media_composer

DOCS = os.path.expanduser("~/Documents")
CLIP = os.path.join(DOCS, "clip1.mov")
OUTPUT = os.path.join(DOCS, "merged.mp4")

state = appui.State(
    input_path=CLIP,
    output_path=OUTPUT,
    result="—",
    status="准备好素材后点击合成",
)


def run_merge():
    if not os.path.exists(state.input_path):
        state.batch_update(
            result="—",
            status=f"找不到源文件: {state.input_path}",
        )
        return

    try:
        path = media_composer.merge_videos([state.input_path], state.output_path)
        state.batch_update(
            result=path or state.output_path,
            status="合成完成",
        )
    except media_composer.MediaComposerError as exc:
        state.batch_update(
            result="—",
            status=f"失败: {exc}",
        )


def body():
    exists = "存在" if os.path.exists(state.input_path) else "缺失"
    return appui.NavigationStack(
        appui.Form([
            appui.Section("素材", [
                appui.LabeledContent("源视频", value=state.input_path),
                appui.LabeledContent("状态", value=exists),
                appui.LabeledContent("输出", value=state.output_path),
            ]),
            appui.Section("操作", [
                appui.Button("合并导出 MP4", action=run_merge)
                .button_style("bordered_prominent"),
                appui.LabeledContent("结果", value=state.result),
                appui.Text(state.status).foreground_color("secondaryLabel"),
            ], footer="请先把 clip1.mov 放到 Documents;合成可能耗时。"),
        ]).navigation_title("视频合成")
    )


appui.run(body, state=state)

#API 参考

#速查

API作用
merge_videos(paths, output_path)按顺序拼接视频
merge_audio(video_path, audio_path, output_path)视频 + 音轨合成
export(input_path, output_path, format)转码/导出
MediaComposerError操作失败时抛出

#merge_videos

merge_videos(paths, output_path) -> str

python
path = media_composer.merge_videos(
    ["part1.mov", "part2.mov"],
    "final.mp4",
)

按列表顺序拼接各文件的视频轨道;无视频轨的文件会被跳过。返回输出路径。

#merge_audio

merge_audio(video_path, audio_path, output_path) -> str

python
path = media_composer.merge_audio(
    "silent.mov",
    "voice.m4a",
    "with_audio.mp4",
)

取视频的画面轨与音频文件的音轨,时长取两者较短者。

#export

export(input_path, output_path, format="mp4") -> str

python
path = media_composer.export("input.mov", "output.mp4")

format 为兼容参数;当前 Bridge 统一导出 MP4。

#异常

code含义
invalid_input路径缺失或列表为空
compose_failed无法创建合成轨道
export_failed导出会话失败或超时

#常见错误

错误写法后果修正
body() 里合成每次刷新都重跑放进按钮回调
源文件不存在export_failed / 空输出os.path.exists()
paths 列表invalid_input至少提供一个视频
合成中反复点按钮重复阻塞加状态锁或禁用按钮

#相关文档

文档用途
video_recorder采集视频素材
avplayer预览合成结果
photos保存视频到相册
audio_recorder采集配音素材

#预期效果

运行示例后,界面应出现文档描述的目标结果;若与预期不符,先看「失败路径」并按返回值或日志排查。