Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

支持 SSML 的 duration 属性 #103

Open
ZhangTianrong opened this issue Nov 26, 2023 · 2 comments
Open

支持 SSML 的 duration 属性 #103

ZhangTianrong opened this issue Nov 26, 2023 · 2 comments
Labels
help wanted Extra attention is needed

Comments

@ZhangTianrong
Copy link

运行环境

  • 操作系统 (Linux/macOS/Windows):Linux
  • 部署方式 (Docker/windows快速部署包/自己搭的环境):自己搭的环境
  • Python 版本 (如果是部署包可不填):3.10
  • 代码版本/部署包版本: 95f4295

问题描述

能否支持 SSML 的 duration attribute? 像是字幕之类的文件翻译成 SSML 后会带有 duration, 并只依靠 duration 和 break 来完成时间上的对齐。生成完一句话之后才能测量时长并修改 break 的时间重新对其。

问题复现步骤

N/A

@Artrajz
Copy link
Owner

Artrajz commented Nov 26, 2023

个人对这个功能还是比较感兴趣的,但是最近比较忙,新功能需要等到大概12月底才有空写,而且用duration来控制语音合成出来的长度我目前也不知道如何实现,得等之后再去研究了。

如果有人有思路的话也可以提供下,非常感谢~

@Artrajz Artrajz added the help wanted Extra attention is needed label Nov 26, 2023
@ZhangTianrong
Copy link
Author

ZhangTianrong commented Nov 26, 2023

个人对这个功能还是比较感兴趣的,但是最近比较忙,新功能需要等到大概12月底才有空写,而且用duration来控制语音合成出来的长度我目前也不知道如何实现,得等之后再去研究了。

如果有人有思路的话也可以提供下,非常感谢~

我设想的其实比较简单,只是单纯为了对齐每句话的起始位置,用来给有翻译的音声配一个 shadow 的翻译,免得一个闭目用的东西非得睁着眼睛看字幕(有点像许多播放器的 text to speech 功能,但是语音生硬,音量还不好调整),所以并不考虑改动每句话的语速来完全 match duration (毕竟 SRT 转 SSML 其实 duration 也并不准确,话说完了字幕并不会清空),只是给每个带有 duration attribute 的 voice element 后补一个 time 为 -1 的 break element, 每次遇到这种 break 时通过上一个 voice 的 duration 和 audio 的长度确定当前 break 长度,如果是负的就暂时直接把上一个 audio 尾部多出来的部分删除。不过如果要边生成变 trial and error length 似乎也没有多困难,在 duration 外设置一个 tolerance, 控制最长和最短时长,然后继续通过 -1 break 元素对齐时间(我是有这个需求才开始了解 VITS 的,可能有其他可以调的方式活着需要注意的参数,只是我不知道)。其实我这个需求最好直接生成每个句子的起始锚点,然后新增的 audio 直接插入对应位置就好了,但是考虑到 SSML 好像是一个比较通行的表达方式,而它似乎用的是 duration 所以才打算还是绕一下路来实现,设置左 tolerance 为 0 倍 duration, 右 tolerance 为 1 倍即可。

Edit:
简单在这里尝试修改一下,测试还有点问题,有空我再看看。

Edit:
结果发现好像没什么问题,只是单纯 test_api.py 中的 "蓊蓊" 两个字是 <UNK> 然后无法 handle 了……我以为这个 test 本来肯定是可以过的啊。

Edit:
目前的效果就是每个 <voice> 元素可以有 duration, duration_min, duration_max 3 个 attribute:

  • duration 就是这句话持续的时间,值和 <break>time 格式一致,不论生成的语音长度为多少,最后都会通过停顿补足到 duration 的长度
  • duration_min(>=0, 默认为 0), duration_max(<=1, 默认为 1) 是允许生成的音频的最短和最长时间和 duration 的比例,生成时会以 10% 的步长调节原始 length 以保证最终音频不长于 duration_max × duration, 也不短于 duration_min × duration

<voice> 元素本身就含有 <break> 时,只能所有部分共用上述 attributes, 如果总长度超过了 duration, 将会直接从末尾截断。如果一定要用这种格式,那只能人为给这句话分配一个较小的 duration_max, 比如分了 3 段,然后给一个 0.33 之类的 duration_max.

暂时用上去好像没啥问题,我有空再完善一下,比如重试多少次无法达成要求的持续时间区间就退出啊之类的,然后看看能不能 PR 吧。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants