Pixelle-Video 源码解析 #19:背景音乐系统:内置 BGM 和自定义音乐如何处理?

前面第 17 篇和第 18 篇,我们分析了 Pixelle-Video 的 TTS 语音生成和声音克隆。

到这里,声音部分已经有了第一层:

narration
    ↓
TTS / 声音克隆
    ↓
frame.audio_path
    ↓
每个视频片段的人声旁白

但一条短视频只有人声,通常还不够完整。

很多知识类、情绪类、故事类、产品介绍类短视频,都需要一层轻微的背景音乐来增强氛围。

所以 Pixelle-Video 在最终视频合成阶段,还支持添加 BGM。README 里也把“添加背景音乐”列为自动生成流程的一部分,并说明 WebUI 的背景音乐有三种选择:无 BGM、内置音乐、自定义音乐。

这一篇我们就专门分析:

Pixelle-Video 的背景音乐系统是怎么设计的?内置 BGM 和自定义音乐最终是如何混入视频的?

一、BGM 在 Pixelle-Video 流程中的位置

先看完整视频生成流程。

前面每个 StoryboardFrame 都会被处理成一个独立视频片段:

frame.narration
    ↓
TTS 生成 audio_path
    ↓
生成图片 / 视频素材
    ↓
HTML 模板合成画面
    ↓
生成 frame.video_segment_path

当所有 frame 都处理完成后,才进入后期合成阶段:

frame_01_segment.mp4
frame_02_segment.mp4
frame_03_segment.mp4
    ↓
concat_videos()
    ↓
拼接成完整视频
    ↓
可选:添加 BGM
    ↓
final.mp4

也就是说,BGM 不是每个 frame 单独加一次,而是在最终拼接阶段统一处理。

源码中的 StandardPipeline.post_production() 正是这样做的:先收集所有 frame.video_segment_path,然后调用 VideoService.concat_videos(),并把 bgm_pathbgm_volumebgm_mode 一起传进去。

这一点很重要。

如果每个片段单独加 BGM,再拼接,很容易出现音乐断点、节奏割裂、片段之间音量不统一的问题。

Pixelle-Video 选择在最终视频层统一加 BGM,更符合后期制作逻辑。

二、BGM 和 TTS 的关系

Pixelle-Video 的声音系统可以分成两层。

第一层是 TTS 人声:

每个 frame 的 narration
    ↓
生成一段人声 audio_path
    ↓
和当前画面合成 segment

第二层是 BGM:

所有 segment 拼接完成
    ↓
对完整视频添加背景音乐

这两层不要混淆。

TTS 是内容本身。
BGM 是氛围增强。

TTS 决定每个分镜讲什么、讲多长。
BGM 不决定分镜结构,只是在最后给完整视频加一层音乐氛围。

所以 Pixelle-Video 的声音合成顺序是:

先人声
    ↓
再视频片段
    ↓
再完整视频
    ↓
最后混入背景音乐

这种顺序的好处是:
人声永远是主音轨,BGM 只是辅助,不会反过来影响 narration、frame duration 和 segment 合成。

三、WebUI 中的三种 BGM 模式

从使用层看,Pixelle-Video 的 BGM 主要有三种模式:

无 BGM
内置音乐
自定义音乐

README 中对这三种模式的描述很直接:无 BGM 表示纯人声解说;内置音乐表示选择预置背景音乐,例如 default.mp3;自定义音乐则是把自己的 MP3、WAV 等音乐文件放到 bgm/ 文件夹,并且可以点击“试听 BGM”进行预览。

可以理解成:

无 BGM:
    final.mp4 只有 TTS 旁白,没有背景音乐。

内置音乐:
    从项目自带 bgm/ 目录选择一首音乐。

自定义音乐:
    用户放入自己的音乐文件,让系统在资源扫描时发现并使用。

这三种模式覆盖了大多数普通短视频场景。

如果是知识讲解、教程视频,有时不加 BGM 更干净。
如果是情绪类、故事类视频,加轻微 BGM 会更有氛围。
如果是品牌账号或固定栏目,自定义音乐能保持账号识别度。

四、参数入口:bgm_path、bgm_volume、bgm_mode

从源码角度看,BGM 进入后期合成主要靠三个参数:

bgm_path
bgm_volume
bgm_mode

StandardPipeline.post_production() 中,调用 VideoService.concat_videos() 时传入:

final_video_path = video_service.concat_videos(
    videos=segment_paths,
    output=ctx.final_video_path,
    bgm_path=ctx.params.get("bgm_path"),
    bgm_volume=ctx.params.get("bgm_volume", 0.2),
    bgm_mode=ctx.params.get("bgm_mode", "loop")
)

源码里默认 bgm_volume0.2,默认 bgm_mode"loop"

这三个参数可以这样理解:

bgm_path:
    背景音乐文件名或路径。
    为空时,不添加 BGM。

bgm_volume:
    背景音乐音量。
    默认 0.2,表示相对较低的背景音量。

bgm_mode:
    背景音乐播放方式。
    loop 表示循环播放。
    once 表示只播放一次。

所以 Pixelle-Video 的 BGM 控制并不复杂,但已经覆盖了最关键的几个点:选哪首、声音多大、是否循环。

五、没有 BGM 时:直接拼接视频片段

先看最简单的情况:没有 BGM。

如果 bgm_path 为空,VideoService.concat_videos() 会直接拼接所有视频片段,不会再进入添加音乐的分支。源码中 concat_videos() 的参数注释也明确写到,bgm_path 是可选背景音乐路径,None 表示不加 BGM。

流程是:

segment_paths
    ↓
concat_videos(videos=segment_paths, bgm_path=None)
    ↓
_concat_demuxer() 或 _concat_filter()
    ↓
final.mp4

这种模式适合:

教程类视频
代码讲解视频
严肃科普视频
需要突出人声的口播视频
后续还要在剪辑软件里单独处理音乐的视频

无 BGM 的优点是干净,缺点是氛围感弱。

六、有 BGM 时:先拼接,再加音乐

如果 bgm_path 不为空,Pixelle-Video 会进入另一条流程。

源码中 VideoService.concat_videos() 的逻辑是:

1. 先把多个视频片段拼接成临时文件
2. 临时文件名类似 final_no_bgm.mp4
3. 再调用 _add_bgm_to_video()
4. 把 BGM 混入最终 output
5. 删除临时 no_bgm 文件

这一段在源码里非常清楚:如果需要 BGM,会先生成 temp_output = output.replace('.mp4', '_no_bgm.mp4'),然后拼接视频,再调用 _add_bgm_to_video(),最后删除临时文件。

完整流程可以画成这样:

frame_01_segment.mp4
frame_02_segment.mp4
frame_03_segment.mp4
    ↓
concat
    ↓
final_no_bgm.mp4
    ↓
_add_bgm_to_video()
    ↓
final.mp4

这个设计很合理。

因为 BGM 应该覆盖整条成片,而不是覆盖单个片段。

先拼接,再混音,可以让音乐贯穿完整视频。

七、为什么要生成 final_no_bgm.mp4?

final_no_bgm.mp4 是一个中间文件。

它的作用是把“视频拼接”和“BGM 混音”拆成两个步骤。

步骤一:
    多个 segment → 一个完整无背景音乐视频

步骤二:
    完整无 BGM 视频 + BGM → 最终视频

这样做有几个好处。

第一,逻辑清楚。

拼接视频是拼接问题。
添加 BGM 是混音问题。
两者拆开,代码更容易维护。

第二,方便排查。

如果最终视频出问题,可以先检查无 BGM 版本是否正常。
如果无 BGM 版本正常,问题大概率在音乐路径、音量或混音阶段。

第三,避免每个 segment 单独处理音乐。

如果每段都加音乐,后面再拼接,音乐会在每个片段重新开始。
统一在完整视频上加音乐,听感更自然。

第四,方便未来扩展。

如果后续要做自动配乐、音量 ducking、淡入淡出,都可以基于无 BGM 成片继续处理。

八、BGM 文件路径如何解析?

BGM 的 bgm_path 既可以是直接路径,也可以只是一个文件名。

VideoService._resolve_bgm_path() 专门负责解析音乐文件路径。源码注释中写明,它的搜索优先级是:

1. 直接路径
2. data/bgm/{filename}
3. bgm/{filename}

如果找不到,就会抛出 FileNotFoundError,并列出尝试过的路径和可用 BGM 文件。

这说明 Pixelle-Video 的 BGM 文件不是只能放在项目默认目录。

它支持两类资源:

默认资源:
    bgm/

自定义资源:
    data/bgm/

os_util.py 中的资源管理函数也体现了这个设计:get_resource_path("bgm", filename) 会优先查找 data/bgm 下的自定义资源,再回退到项目根目录下的默认 bgmlist_resource_files("bgm") 会合并默认目录和自定义目录,并且自定义文件优先覆盖同名默认文件。

所以,如果用户放了一个和内置音乐同名的文件到 data/bgm/,系统会优先使用用户自定义版本。

九、内置 BGM 和自定义 BGM 的本质区别

从用户角度看:

内置 BGM:
    项目自带,直接选择。

自定义 BGM:
    用户自己放进去,再选择。

但从源码角度看,它们最后都是一个 bgm_path

区别只在路径解析阶段。

内置 BGM:
    bgm/default.mp3

自定义 BGM:
    data/bgm/my_music.mp3

当进入 VideoService._add_bgm_to_video() 时,它并不关心这首音乐来自哪里。

它只需要拿到一个真实存在的音频文件路径:

resolved_bgm

然后交给 add_bgm() 去混音。

这就是资源系统的好处:

上层只传文件名
资源层负责查找
视频层只处理真实路径

这样内置音乐和自定义音乐就能共用同一套混音逻辑。

十、Docker 场景下自定义 BGM 放哪里?

如果使用 Docker 部署,Pixelle-Video 也考虑了自定义资源持久化。

docker-compose.yml 中会把宿主机的 ./data 挂载到容器的 /app/data,注释里说明 data/ 包含 users/bgm/templates/workflows/ 等自定义资源;默认资源则已经打包在镜像中,自定义资源可以覆盖默认资源。

也就是说,Docker 用户应该把自定义音乐放到类似:

./data/bgm/

而不是直接改容器里的:

/app/bgm/

因为容器里的文件可能随着重建镜像而丢失。

正确思路是:

宿主机 ./data/bgm/custom.mp3
    ↓
挂载到容器 /app/data/bgm/custom.mp3
    ↓
Pixelle-Video 资源系统优先读取 data/bgm

这个设计和模板、workflow 的自定义机制是一致的。

十一、_list_available_bgm:系统如何列出可用音乐?

VideoService._list_available_bgm() 用来列出可用 BGM 文件。

源码中它调用 list_resource_files("bgm"),然后只保留音频扩展名:

.mp3
.wav
.ogg
.flac
.m4a
.aac

最后返回排序后的文件名列表。

这说明 Pixelle-Video 的 BGM 文件并不只支持 MP3。

从路径解析和列表过滤看,它至少考虑了常见音频格式:

mp3
wav
ogg
flac
m4a
aac

不过从 WebUI 文档描述看,最常见的使用方式还是 MP3 / WAV。

实际使用时,如果追求兼容性,建议优先使用:

mp3
wav

这两个格式通常最稳定。

十二、_add_bgm_to_video:从路径解析到混音

真正添加背景音乐的入口是:

VideoService._add_bgm_to_video()

它做两件事。

第一,调用 _resolve_bgm_path(),把用户传入的 bgm_path 解析成真实文件路径。

第二,根据 bgm_mode 判断是否循环播放,然后调用 add_bgm() 完成混音。

源码里 mode == "loop" 时,loop = True;否则就是只播放一次。

简化逻辑如下:

def _add_bgm_to_video(video, bgm_path, output, volume=0.2, mode="loop"):
    resolved_bgm = self._resolve_bgm_path(bgm_path)
    loop = (mode == "loop")
    return self.add_bgm(
        video=video,
        bgm=resolved_bgm,
        output=output,
        bgm_volume=volume,
        loop=loop,
        fade_in=0.0
    )

这一步把用户层参数转换成视频处理层参数:

bgm_path → resolved_bgm
bgm_mode → loop
bgm_volume → bgm_volume

然后真正交给 ffmpeg 混音。

十三、add_bgm:ffmpeg 如何混合人声和背景音乐?

add_bgm() 是 BGM 混音的核心函数。

源码注释中写得很明确:它会把 BGM 添加到视频中,bgm_volume 表示背景音乐相对于原始声音的音量,loop=True 时会循环 BGM 来匹配视频时长,并且 BGM 会和原视频音频混合。

它内部的关键逻辑可以理解为:

输入视频
    ↓
取出原视频音频,也就是 TTS 旁白

输入 BGM
    ↓
必要时 stream_loop=-1 无限循环

BGM 音频
    ↓
volume 过滤器调低音量

原视频音频 + BGM 音频
    ↓
amix 混音
    ↓
输出 final.mp4

源码中使用的是 ffmpeg 的 amix 过滤器,并设置 duration='first',也就是输出音频长度跟随第一个输入,也就是原视频音频长度。

这点非常关键。

因为最终视频长度应该由完整视频决定,而不是由 BGM 决定。

如果 BGM 比视频长,不应该把视频拉长。
如果 BGM 比视频短,在 loop 模式下可以循环补齐。
如果不是 loop 模式,则音乐播放一次后结束。

十四、bgm_mode:loop 和 once 的区别

Pixelle-Video 的 bgm_mode 有两个主要值:

loop
once

_add_bgm_to_video() 中,mode == "loop" 会转成 loop=True,然后 add_bgm() 在读取 BGM 时使用 stream_loop=-1,表示无限循环;否则不循环。

可以理解成:

loop:
    BGM 不够长时循环播放,直到视频结束。

once:
    BGM 只播放一次,播完就没有背景音乐。

两种模式适合不同场景。

1. loop 模式

适合大多数短视频。

因为短视频长度不固定,如果 BGM 太短,loop 可以自动补齐。

30 秒视频 + 10 秒 BGM
    ↓
BGM 循环 3 次

优点是不会出现后半段突然没有音乐的问题。
缺点是如果 BGM 结尾和开头衔接不好,循环点可能会有跳变。

2. once 模式

适合 BGM 本身已经足够长,或者你希望音乐只出现一次的场景。

20 秒视频 + 60 秒 BGM
    ↓
只取前 20 秒混入最终视频

或者:

60 秒视频 + 15 秒 BGM
    ↓
前 15 秒有音乐,后面主要保留人声

once 模式更适合有明确音乐结构的内容,例如开场音乐、结尾音乐、短提示音等。

十五、bgm_volume:为什么默认比较低?

Pixelle-Video 在 post_production() 里传给 concat_videos() 的默认 bgm_volume0.2

这个默认值比较保守。

原因很简单:

Pixelle-Video 的主音轨是 TTS 旁白。

BGM 如果太大,会压住人声,尤其是中文口播、知识科普、教程类视频,观众听不清内容就会直接划走。

所以 BGM 音量应该遵循一个原则:

人声优先
音乐辅助

经验上可以这样理解:

0.1 - 0.2:
    适合知识类、教程类、严肃口播。

0.2 - 0.3:
    适合普通情绪类、故事类短视频。

0.3 以上:
    需要谨慎,可能会影响人声清晰度。

当然,具体还要看原始 BGM 的响度。
有些音乐本身很响,0.2 也可能偏大。
有些音乐本身很轻,0.3 也未必明显。

所以后续如果产品化,可以增加响度标准化或自动 ducking。

十六、为什么 BGM 不参与每个 frame 的 duration?

前面讲 TTS 时,我们说 frame.duration 由 TTS 音频时长决定。

那么 BGM 会不会影响 frame.duration

答案是:不会。

BGM 是在完整视频拼接之后统一添加的,不参与单个 frame 的生成。源码里 post_production() 是在 produce_assets() 之后执行;frame 已经生成了 video_segment_path,BGM 才通过 concat_videos() 的参数进入后期阶段。

这说明:

TTS 决定片段时长
BGM 不决定片段时长
BGM 只覆盖最终视频音轨

这种设计很合理。

因为 BGM 是背景层,不应该打乱旁白节奏。
如果音乐长度反过来决定视频长度,就会让文案、分镜和画面都变得不可控。

十七、BGM 和最终视频编码

add_bgm() 中,ffmpeg 输出时使用:

vcodec='copy'
acodec='aac'
audio_bitrate='192k'

源码中可以看到,视频流会尽量直接复制,而音频流重新编码为 AAC。

这说明添加 BGM 时,Pixelle-Video 的重点是处理音频,不是重新渲染视频画面。

视频画面:
    尽量 copy,减少重编码损耗和耗时。

音频:
    人声 + BGM 混音后重新编码成 AAC。

这也是合理的。

因为 BGM 混音会改变音频轨,音频必须重新编码;
但视频画面没有变化,能 copy 就 copy,可以节省时间。

十八、当前 BGM 系统的优点

Pixelle-Video 的 BGM 系统虽然不复杂,但设计很实用。

1. 接入位置合理

BGM 在最终视频拼接后统一添加,避免每个 segment 音乐重复开始。

2. 支持无 BGM

对教程、技术讲解、严肃内容很重要。

3. 支持内置音乐

新用户不用准备素材,直接使用项目自带音乐。

4. 支持自定义音乐

用户可以把自己的音乐放进 bgm/data/bgm/,用于账号风格统一。

5. 支持 custom override

资源系统优先读取 data/bgm,再读取默认 bgm,方便 Docker 和产品化部署。

6. 支持循环播放

短视频长度不固定,loop 模式能避免音乐中途结束。

7. 音量可控

bgm_volume 可以控制背景音乐强度,默认 0.2 比较适合以旁白为主的视频。

十九、当前 BGM 系统的局限

当然,当前 BGM 系统也有一些局限。

1. BGM 不理解视频内容

目前 BGM 更像“用户选择一首音乐,然后混进去”。

它不会自动判断这条视频是励志、悬疑、温暖、科技感,还是搞笑。

2. 没有自动卡点

BGM 不会根据分镜切换点、情绪变化或结尾高潮自动调整节奏。

3. 没有自动 ducking

当人声出现时,BGM 最好自动压低;人声停顿时,BGM 可以稍微抬高。

当前逻辑主要是固定 bgm_volume 混音,还没有做人声侧链压缩或自动避让。

4. 淡出还不完整

add_bgm() 参数里有 fade_infade_out,但源码注释说明 fade_out 暂未实现,因为需要先知道视频时长,再计算淡出起点。

5. 版权问题需要用户自己注意

自定义音乐虽然方便,但音乐是否可商用、是否会被平台识别版权,仍然需要用户自己确认。

二十、GitHub Issue 中提到的第四种模式:自动生成 BGM

Pixelle-Video 目前常见模式是无 BGM、内置音乐、自定义音乐。

不过项目社区里已经有人提出“第四种模式”:根据成片自动生成 BGM。这个 issue 的思路是,在视频合成完成后,把成片交给配乐模型,根据视频节奏和情绪自动生成原创背景音乐,再通过 ffmpeg 混音。

这个建议很有意思。

因为它刚好补上了当前 BGM 系统的一个短板:

当前:
    用户选音乐,音乐不理解视频内容。

自动生成 BGM:
    根据成片生成音乐,音乐更贴合视频节奏和情绪。

如果未来实现,可以形成四种 BGM 模式:

none:
    不加 BGM。

builtin:
    使用内置音乐。

custom:
    使用用户上传音乐。

generated:
    根据最终视频自动生成 BGM。

从 Pixelle-Video 现有架构看,这个扩展点也比较自然,因为当前系统已经有了:

final_no_bgm.mp4
    ↓
_add_bgm_to_video()
    ↓
final.mp4

只要在中间插入一步:

final_no_bgm.mp4
    ↓
BGM generation API
    ↓
generated_bgm.mp3
    ↓
_add_bgm_to_video()
    ↓
final.mp4

就能比较顺地接入。

二十一、二次开发:如何让 BGM 更智能?

如果基于 Pixelle-Video 继续开发,BGM 系统有不少增强空间。

1. 增加 BGM 分类

可以把音乐按情绪分类:

warm
sad
epic
calm
funny
tech
suspense
inspiring

用户选择视频类型后,系统自动推荐音乐。

2. 增加自动 ducking

当 TTS 人声出现时,自动降低 BGM:

人声开始:
    BGM 降低到 15%

人声停顿:
    BGM 回升到 25%

这样能兼顾氛围和清晰度。

3. 增加结尾淡出

可以先读取最终视频时长,再计算 fade_out 起点:

video_duration = 45s
fade_out = 3s
fade_out_start = 42s

然后对 BGM 应用淡出滤镜。

4. 增加 BGM 预处理

自定义音乐可能有音量过大、前奏太长、格式不兼容等问题。

可以自动处理:

转码为统一格式
裁剪前奏
音量标准化
循环点优化
响度检测

5. 增加按分镜情绪配乐

更高级的做法是根据每个 frame 的 narration 判断情绪,然后动态切换 BGM 或调整音量。

例如:

开头悬念:
    suspense

中间解释:
    calm

结尾鼓励:
    inspiring

不过这会明显增加合成复杂度。

6. 增加自动生成 BGM

参考社区 issue 的方向,可以在 final_no_bgm.mp4 生成后调用配乐模型生成一条匹配视频的 BGM,再混入最终视频。

这会让 Pixelle-Video 从“选择音乐”升级为“自动配乐”。

二十二、常见问题排查

1. 选择了 BGM,但最终视频没有音乐

优先检查:

bgm_path 是否为空
BGM 文件是否存在
文件是否放在 bgm/ 或 data/bgm/
文件扩展名是否是支持的音频格式
ffmpeg 是否能读取该音频文件

_resolve_bgm_path() 找不到文件时会抛出错误,并列出尝试过的路径和可用 BGM 文件。

2. 自定义音乐不显示

检查:

是否放到了正确目录
Docker 下是否放在 ./data/bgm/
文件扩展名是否是 mp3 / wav / ogg / flac / m4a / aac
是否和默认文件重名

资源系统会合并默认目录和 data/bgm,并对同名文件使用自定义版本。

3. BGM 太大,盖住人声

降低:

bgm_volume

默认是 0.2,如果仍然太大,可以调到:

0.1
0.05

4. BGM 播一半没了

检查 bgm_mode

如果是 once,音乐只播放一次。
如果希望全程都有音乐,应使用:

bgm_mode = loop

5. BGM 循环点很突兀

这是音乐素材本身的问题。

解决方式:

换一首更适合循环的音乐
提前剪辑成无缝循环版本
使用更长的 BGM
后续增加 crossfade loop

6. 添加 BGM 时报 ffmpeg 错误

可能是:

ffmpeg 没安装
音频格式不兼容
BGM 文件损坏
路径中有特殊字符
视频原音轨异常

VideoService 在执行视频处理前会检查系统是否安装了 ffmpeg,找不到会抛出安装提示。

二十三、源码阅读建议

如果你要阅读 Pixelle-Video 的 BGM 相关源码,建议按这个顺序:

1. README.md
   看 WebUI 中 BGM 的三种模式:无 BGM、内置音乐、自定义音乐。

2. pixelle_video/pipelines/standard.py
   看 post_production() 如何把 bgm_path、bgm_volume、bgm_mode 传给 concat_videos()。

3. pixelle_video/services/video.py
   看 concat_videos() 如何先拼接 segment,再调用 _add_bgm_to_video()。

4. pixelle_video/services/video.py
   看 _resolve_bgm_path() 如何解析直接路径、data/bgm 和默认 bgm 目录。

5. pixelle_video/services/video.py
   看 add_bgm() 如何用 ffmpeg 的 volume 和 amix 混合人声与 BGM。

6. pixelle_video/utils/os_util.py
   看资源系统如何支持 data/bgm 覆盖默认 bgm。

7. docker-compose.yml
   如果用 Docker,看 ./data 如何挂载到 /app/data,保证自定义 BGM 持久化。

这条路线可以完整串起:

用户选择 BGM
    ↓
bgm_path / bgm_volume / bgm_mode
    ↓
post_production()
    ↓
concat_videos()
    ↓
_resolve_bgm_path()
    ↓
add_bgm()
    ↓
final.mp4

二十四、总结

这一篇我们分析了 Pixelle-Video 的背景音乐系统。

它的核心链路是:

所有 frame 生成 segment
    ↓
StandardPipeline.post_production()
    ↓
收集 frame.video_segment_path
    ↓
VideoService.concat_videos()
    ↓
如果没有 bgm_path:
        直接拼接成 final.mp4

    如果有 bgm_path:
        先拼接成 final_no_bgm.mp4
        再解析 BGM 路径
        再用 ffmpeg 混合原视频人声和 BGM
        输出 final.mp4

从设计上看,Pixelle-Video 的 BGM 系统有几个关键点:

BGM 在最终成片阶段统一添加。
TTS 人声是主音轨,BGM 是辅助氛围。
bgm_path 为空时不加 BGM。
内置音乐和自定义音乐最后都会解析成真实文件路径。
data/bgm 优先级高于默认 bgm,适合自定义和 Docker 部署。
bgm_volume 控制背景音乐音量。
bgm_mode 控制音乐播放一次还是循环。
ffmpeg 的 amix 负责把人声和背景音乐混合。

一句话总结:

Pixelle-Video 的 BGM 系统,本质是在所有视频片段拼接完成后,把内置或自定义音乐解析成真实音频路径,再通过 ffmpeg 将其以指定音量和循环模式混入最终视频的人声轨道中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天进步2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值