Go语言全能配置管理库
Viper是Go语言的全能配置管理库,支持JSON、TOML、YAML等多种格式。它能从文件、环境变量、命令行标志和远程系统读取配置,提供默认值设置、实时监控、别名注册等功能。Viper采用优先级处理机制,简单易用yet功能强大,适用于各类Go项目的配置需求。
Viper v2 反馈
Viper 正在向 v2 版本迈进,我们非常希望听到 你 对它的想法。请在这里分享你的想法:https://forms.gle/R6faU74qPRPAzchZ9
感谢你!
Go 配置利器!
许多 Go 项目都使用 Viper 构建,包括:
go get github.com/spf13/viper
注意: Viper 使用 Go Modules 来管理依赖。
Viper 是一个完整的 Go 应用程序配置解决方案,包括 12-Factor 应用。它被设计用于在应用程序中工作 ,可以处理所有类型的配置需求和格式。它支持:
Viper 可以被视为你的应用程序所有配置需求的注册表。
在构建现代应用程序时,你不想担心配置文件格式;你想专注于构建出色的软件。Viper 就是为此而生的。
Viper 为你做以下工作:
Viper 使用以下优先顺序。每个项目优先于其下方的项目:
Set
重要: Viper 配置键不区分大小写。 目前正在讨论是否将其设为可选。
一个好的配置系统应该支持默认值。虽然键不需要默认值,但在未通过配置文件、环境变量、远程配置或标志设置键的情况下,默认值很有用。
示例:
viper.SetDefault("ContentDir", "content") viper.SetDefault("LayoutDir", "layouts") viper.SetDefault("Taxonomies", map[string]string{"tag": "tags", "category": "categories"})
Viper 需要最少的配置,以便知道在哪里查找配置文件。Viper 支持 JSON、TOML、YAML、HCL、INI、envfile 和 Java Properties 文件。Viper 可以搜索多个路径,但目前单个 Viper 实例只支持单个配置文件。Viper 不默认任何配置搜索路径,将默认决策留给应用程序。
以下是如何使用 Viper 搜索和读取配置文件的示例。不需要特定的路径,但应提供至少一个预期存在配置文件的路径。
viper.SetConfigName("config") // 配置文件名(不带扩展名) viper.SetConfigType("yaml") // 如果配置文件名中没有扩展名,则需要指定 viper.AddConfigPath("/etc/appname/") // 查找配置文件的路径 viper.AddConfigPath("$HOME/.appname") // 可多次调用以添加多个搜索路径 viper.AddConfigPath(".") // 可选,在工作目录中查找配置 err := viper.ReadInConfig() // 查找并读取配置文件 if err != nil { // 处理读取配置文件错误 panic(fmt.Errorf("fatal error config file: %w", err)) }
你可以这样处理未找到配置文件的特定情况:
if err := viper.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); ok { // 未找到配置文件;如果需要可以忽略错误 } else { // 找到配置文件但产生了另一个错误 } } // 找到配置文件并成功解析
注意 [自 1.6 起]: 你也可以使用没有扩展名的文件,并以 编程方式指定格式。适用于那些位于用户主目录中没有任何扩展名的配置文件,如 .bashrc
从配置文件读取很有用,但有时你想存储运行时所做的所有修改。为此,有一系列命令可用,每个命令都有其特定用途:
根据经验,所有标记为安全的操作都不会覆盖任何文件,只会在不存在时创建;而默认行为是创建或截断。
以下是一些小例子:
viper.WriteConfig() // 将当前配置写入由 'viper.AddConfigPath()' 和 'viper.SetConfigName' 设置的预定义路径 viper.SafeWriteConfig() viper.WriteConfigAs("/path/to/my/.config") viper.SafeWriteConfigAs("/path/to/my/.config") // 因为已经写入,所以会报错 viper.SafeWriteConfigAs("/path/to/my/.other_config")
Viper 支持让你的应用程序在运行时实时读取配置文件的能力。
不再需要重启服务器来使配置生效,使用 viper 的应用程序可以在运行时读取配置文件的更新,而不会中断。
只需告诉 viper 实例监视配置。你也可以选择提供一个函数,让 Viper 在每次发生变化时运行。
确保在调用 WatchConfig()
之前添加所有的 configPaths
viper.OnConfigChange(func(e fsnotify.Event) { fmt.Println("配置文件发生变化:", e.Name) }) viper.WatchConfig()
Viper 预定义了许多配置源,如文件、环境变量、标志和远程 K/V 存储,但你并不局限于这些。你也可以实现自己需要的配置源并将其提供给 viper。
viper.SetConfigType("yaml") // 或 viper.SetConfigType("YAML") // 在程序中引入此配置的任何方法。 var yamlExample = []byte(` Hacker: true name: steve hobbies: - skateboarding - snowboarding - go clothing: jacket: leather trousers: denim age: 35 eyes : brown beard: true `) viper.ReadConfig(bytes.NewBuffer(yamlExample)) viper.Get("name") // 这将返回 "steve"
这些可能来自命令行标志或您自己的应用程序逻辑。
viper.Set("Verbose", true) viper.Set("LogFile", LogFile) viper.Set("host.port", 5899) // 设置子集
别名允许单个值被多个键引用
viper.RegisterAlias("loud", "Verbose") viper.Set("verbose", true) // 与下一行效果相同 viper.Set("loud", true) // 与上一行效果相同 viper.GetBool("loud") // true viper.GetBool("verbose") // true
Viper 完全支持环境变量。这使得 12 因素应用程序开箱即用。有五种方法可以帮助处理环境变量:
AutomaticEnv()
BindEnv(string...) : error
SetEnvPrefix(string)
SetEnvKeyReplacer(string...) *strings.Replacer
AllowEmptyEnv(bool)
在使用环境变量时,重要的是要认识到 Viper 将环境变量视为区分大小写。
Viper 提供了一种机制来尝试确保环境变量是唯一的。通过使用 SetEnvPrefix
,您可以告诉 Viper 在读取环境变量时使用前缀。BindEnv
和 AutomaticEnv
都将使用此前缀。
BindEnv
接受一个或多个参数。第一个参数是键名,其余的是要绑定到此键的环境变量名称。如果提供了多个,它们将按指定的顺序优先。环境变量名称区分大小写。如果未提供环境变量名称,则 Viper 将自动假设环境变量匹配以下格式:前缀 + "_" + 全大写的键名。当您明确提供环境变量名称(第二个参数)时,它不会自动添加前缀。例如,如果第二个参数是 "id",Viper 将查找名为 "ID" 的环境变量。
使用环境变量时要认识到的一个重要事项是,每次访问时都会读取该值。Viper 在调用 BindEnv
时不会固定值。
AutomaticEnv
是一个强大的辅助工具,特别是与 SetEnvPrefix
结合使用时。当被调用时,Viper 将在每次进行 viper.Get
请求时检查环境变量。它将应用以下规则。它将检查名称与键名大写并加上 EnvPrefix
(如果设置)前缀的环境变量。
SetEnvKeyReplacer
允许您使用 strings.Replacer
对象在一定程度上重写环境变量键。如果您想在 Get()
调用中使用 -
或其他字符,但希望环境变量使用 _
分隔符,这将非常有用。使用示例可以在 viper_test.go
中找到。
或者,您可以使用 NewWithOptions
工厂函数的 EnvKeyReplacer
。与 SetEnvKeyReplacer
不同,它接受一个 StringReplacer
接口,允许您编写自定义的字符串替换逻辑。
默认情况下,空环境变量被视为未设置,将回退到下一个配置源。要将空环境变量视为已设置,请使用 AllowEmptyEnv
方法。
SetEnvPrefix("spf") // 将自动转为大写 BindEnv("id") os.Setenv("SPF_ID", "13") // 通常在应用程序外部完成 id := Get("id") // 13
Viper 能够绑定到标志。具体来说,Viper 支持 Cobra 库中使用的 Pflags
。
与 BindEnv
类似,值不是在调用绑定方法时设置的,而是在访问时设置的。这意味着您可以尽早绑定,甚至在 init()
函数中绑定。
对于单个标志,BindPFlag()
方法提供了这种功能。
示例:
serverCmd.Flags().Int("port", 1138, "应用服务器运行的端口") viper.BindPFlag("port", serverCmd.Flags().Lookup("port"))
您还可以绑 定现有的 pflags 集合(pflag.FlagSet):
示例:
pflag.Int("flagname", 1234, "flagname 的帮助信息") pflag.Parse() viper.BindPFlags(pflag.CommandLine) i := viper.GetInt("flagname") // 从 viper 而不是 pflag 中检索值
在 Viper 中使用 pflag 并不妨碍使用其他使用标准库 flag 包的包。pflag 包可以通过导入这些标志来处理为 flag 包定义的标志。这是通过调用 pflag 包提供的名为 AddGoFlagSet() 的便利函数来实现的。
示例:
package main import ( "flag" "github.com/spf13/pflag" ) func main() { // 使用标准库 "flag" 包 flag.Int("flagname", 1234, "flagname 的帮助信息") pflag.CommandLine.AddGoFlagSet(flag.CommandLine) pflag.Parse() viper.BindPFlags(pflag.CommandLine) i := viper.GetInt("flagname") // 从 viper 中检索值 // ... }
如果您不使用 Pflags
,Viper 提供了两个 Go 接口来绑定其他标志系统。
FlagValue
表示单个标志。这是一个非常简单的示例,展示如何实现这个接口:
type myFlag struct {} func (f myFlag) HasChanged() bool { return false } func (f myFlag) Name() string { return "my-flag-name" } func (f myFlag) ValueString() string { return "my-flag-value" } func (f myFlag) ValueType() string { return "string" }
一旦您的标志实现了这个接口,您就可以简单地告诉 Viper 绑定它:
viper.BindFlagValue("my-flag-name", myFlag{})
FlagValueSet
表示一组标志。这是一个非常简单的示例,展示如何实现这个接口:
type myFlagSet struct { flags []myFlag } func (f myFlagSet) VisitAll(fn func(FlagValue)) { for _, flag := range flags { fn(flag) } }
一旦您的标志集实现了这个接口,您就可以简单地告诉 Viper 绑定它:
fSet := myFlagSet{ flags: []myFlag{myFlag{}, myFlag{}}, } viper.BindFlagValues("my-flags", fSet)
要在 Viper 中启用远程支持,请执行 viper/remote
包的空导入:
import _ "github.com/spf13/viper/remote"
Viper 将读取从键/值存储(如 etcd 或 Consul)的路径中检索到的配置字符串( 作为 JSON、TOML、YAML、HCL 或 envfile)。这些值优先于默认值,但会被从磁盘、标志或环境变量检索到的配置值覆盖。
Viper 支持多个主机。要使用,请传递一个由 ;
分隔的端点列表。例如 http://127.0.0.1:4001;http://127.0.0.1:4002
。
Viper 使用 crypt 从键/值存储中检索配置,这意味着您可以加密存储配置值,如果您有正确的 gpg 密钥环,它们会自动解密。加密是可选的。
您可以将远程配置与本地配置结合使用,也可以独立使用。
crypt
有一个命令行助手,您可以用它将配置放入键/值存储中。crypt
默认使用 http://127.0.0.1:4001 上的 etcd。
$ go get github.com/sagikazarmark/crypt/bin/crypt $ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
确认您的值已设置:
$ crypt get -plaintext /config/hugo.json
有关如何设置加密值或如何使用 Consul 的示例,请参阅 crypt
文档。
viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001","/config/hugo.json") viper.SetConfigType("json") // 因为字节流中没有文件扩展名,支持的扩展名有 "json"、"toml"、"yaml"、"yml"、"properties"、"props"、"prop"、"env"、"dotenv" err := viper.ReadRemoteConfig()
viper.AddRemoteProvider("etcd3", "http://127.0.0.1:4001","/config/hugo.json") viper.SetConfigType("json") // 因为字节流中没有文件扩展名,支持的扩展名有 "json"、"toml"、"yaml"、"yml"、"properties"、"props"、"prop"、"env"、"dotenv" err := viper.ReadRemoteConfig()
你需要在Consul键/值存储中设置一个包含所需配置的JSON值的键。
例如,创建一个Consul键/值存储键 MY_CONSUL_KEY
,值为:
{ "port": 8080, "hostname": "myhostname.com" }
viper.AddRemoteProvider("consul", "localhost:8500", "MY_CONSUL_KEY") viper.SetConfigType("json") // 需要明确设置为json err := viper.ReadRemoteConfig() fmt.Println(viper.Get("port")) // 8080 fmt.Println(viper.Get("hostname")) // myhostname.com
viper.AddRemoteProvider("firestore", "google-cloud-project-id", "collection/document") viper.SetConfigType("json") // 配置格式: "json", "toml", "yaml", "yml" err := viper.ReadRemoteConfig()
当然,你也可以使用 SecureRemoteProvider
viper.AddRemoteProvider("nats", "nats://127.0.0.1:4222", "myapp.config") viper.SetConfigType("json") err := viper.ReadRemoteConfig()
viper.AddSecureRemoteProvider("etcd","http://127.0.0.1:4001","/config/hugo.json","/etc/secrets/mykeyring.gpg") viper.SetConfigType("json") // 因为字节流中没有文件扩展名,支持的扩展名有 "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv" err := viper.ReadRemoteConfig()
// 或者,你可以创建一个新的viper实例。 var runtime_viper = viper.New() runtime_viper.AddRemoteProvider("etcd", "http://127.0.0.1:4001", "/config/hugo.yml") runtime_viper.SetConfigType("yaml") // 因为字节流中没有文件扩展名,支持的扩展名有 "json", "toml", "yaml", "yml", "properties", "props", "prop", "env", "dotenv" // 首次从远程配置读取。 err := runtime_viper.ReadRemoteConfig() // 解析配置 runtime_viper.Unmarshal(&runtime_conf) // 开启一个goroutine永久监听远程变更 go func(){ for { time.Sleep(time.Second * 5) // 每次请求后延迟 // 目前,仅测试了etcd支持 err := runtime_viper.WatchRemoteConfig() if err != nil { log.Errorf("无法读取远程配置: %v", err) continue } // 将新配置解析到我们的运行时配置结构中。你也可以使用通道 // 来实现通知系统变更的信号 runtime_viper.Unmarshal(&runtime_conf) } }()
在Viper中,根据值的类型,有几种获取值的方式。 以下函数和方法可用:
Get(key string) : any
GetBool(key string) : bool
GetFloat64(key string) : float64
GetInt(key string) : int
GetIntSlice(key string) : []int
GetString(key string) : string
GetStringMap(key string) : map[string]any
GetStringMapString(key string) : map[string]string
GetStringSlice(key string) : []string
GetTime(key string) : time.Time
GetDuration(key string) : time.Duration
IsSet(key string) : bool
AllSettings() : map[string]any
需要注意的一点是,如果未找到,每个Get函数都会返回零值。要检查给定键是否存在,提供了 IsSet()
方法。
如果值已设置但无法解析为请求的类型,也会返回零值。
示例:
viper.GetString("logfile") // 不区分大小写的设置和获取 if viper.GetBool("verbose") { fmt.Println("已启用详细模式") }
访问器方法也接受格式化的路径来深度嵌套的键。例如,如果加载了以下JSON文件:
{ "host": { "address": "localhost", "port": 5799 }, "datastore": { "metric": { "host": "127.0.0.1", "port": 3099 }, "warehouse": { "host": "198.0.0.1", "port": 2112 } } }
Viper可以通过传递以 .
分隔的键路径来访问嵌套字段:
GetString("datastore.metric.host") // (返回 "127.0.0.1")
这遵循上述建立的优先级规则;将通过剩余的配置注册表级联搜索路径,直到找到为止。
例如,给定这个配置文件,datastore.metric.host
和 datastore.metric.port
都已定义(并可能被覆盖)。如果此外在默认值中定义了 datastore.metric.protocol
,Viper也会找到它。
但是,如果 datastore.metric
被覆盖(通过标志、环境变量、Set()
方法等)为一个直接值,那么 datastore.metric
的所有子键都将变为未定义,它们被更高优先级的配置级别"遮蔽"了。
Viper可以使用路径中的数字访问数组索引。例如:
{ "host": { "address": "localhost", "ports": [ 5799, 6029 ] }, "datastore": { "metric": { "host": "127.0.0.1", "port": 3099 }, "warehouse": { "host": "198.0.0.1", "port": 2112 } } } GetInt("host.ports.1") // 返回 6029
最后,如果存在与分隔键路径匹配的键,将返回其值。例如:
{ "datastore.metric.host": "0.0.0.0", "host": { "address": "localhost", "port": 5799 }, "datastore": { "metric": { "host": "127.0.0.1", "port": 3099 }, "warehouse": { "host": "198.0.0.1", "port": 2112 } } } GetString("datastore.metric.host") // 返回 "0.0.0.0"
在开发可重用模块时,提取配置的子集并将其传递给模块通常很有用。这样,模块可以使用不同的配置多次实例化。
例如,应用程序可能为不同目的使用多个不同的缓存存储:
cache: cache1: max-items: 100 item-size: 64 cache2: max-items: 200 item-size: 80
我们可以将缓存名称传递给模块(例如 NewCache("cache1")
),但这需要奇怪的连接来访问配置键,并且与全局配置的分离程度较低。
因此,我们可以将代表配置子集的Viper实例传递给构造函数:
cache1Config := viper.Sub("cache.cache1") if cache1Config == nil { // 如果找不到键,Sub返回nil panic("未找到缓存配置") } cache1 := NewCache(cache1Config)
注意: 始终检查 Sub
的返回值。如果找不到键,它返回 nil
。
在内部,NewCache
函数可以直接访问 max-items
和 item-size
键:
func NewCache(v *Viper) *Cache { return &Cache{ MaxItems: v.GetInt("max-items"), ItemSize: v.GetInt("item-size"), } }
生成的代码易于测试,因为它与主配置结构解耦,并且更容易重用(出于同样的原因)。
你还可以选择将所有或特定值解析到结构体、映射等中。
有两种方法可以做到这一点:
Unmarshal(rawVal any) : error
UnmarshalKey(key string, rawVal any) : error
示例:
type config struct { Port int Name string PathMap string `mapstructure:"path_map"` } var C config err := viper.Unmarshal(&C) if err != nil { t.Fatalf("无法解码到结构体,%v", err) }
如果你想解析键本身包含点(默认键分隔符)的配置,你必须更改分隔符:
v := viper.NewWithOptions(viper.KeyDelimiter("::")) v.SetDefault("chart::values", map[string]any{ "ingress": map[string]any{ "annotations": map[string]any{ "traefik.frontend.rule.type": "PathPrefix", "traefik.ingress.kubernetes.io/ssl-redirect": "true", }, }, }) type config struct { Chart struct{ Values map[string]any } } var C config v.Unmarshal(&C)
Viper也支持解析到嵌入式结构体:
/* 示例配置: 模块: 启用:true 令牌:89h3f98hbwf987h3f98wenf89ehf */ type config struct { Module struct { Enabled bool moduleConfig `mapstructure:",squash"` } } // moduleConfig 可以在特定模块包中定义 type moduleConfig struct { Token string } var C config err := viper.Unmarshal(&C) if err != nil { t.Fatalf("无法解码到结构体,%v", err) }
Viper 在底层使用 github.com/go-viper/mapstructure 进行值的解析,默认使用 mapstructure
标签。
Viper 的一个常见需求是添加更多的值格式和解码器。 例如,将字符(点、逗号、分号等)分隔的字符串解析为切片。
使用 mapstructure 解码钩子,Viper 已经支持这一功能。
在这篇博客文章中可以了解更多详情。
你可能需要将 Viper 中保存的所有设置序列化为字符串,而不是将它们写入文件。
你可以使用你喜欢的格式的序列化器处理 AllSettings()
返回的配置。
import ( yaml "gopkg.in/yaml.v2" // ... ) func yamlStringSettings() string { c := viper.AllSettings() bs, err := yaml.Marshal(c) if err != nil { log.Fatalf("无法将配置序列化为YAML:%v", err) } return string(bs) }
Viper 默认提供了一个全局实例(单例)。
尽管它使配置设置变得简单,但通常不建议使用它,因为它会使测试变得更困难,并可能导致意外行为。
最佳实践是初始化一个 Viper 实例,并在需要时传递它。
全局实例在将来_可能_会被弃用。 详情请参阅 #1855。
你还可以为你的应用程序创建多个不同的 Viper 实例。每个实例都有自己独特的配置和值集。每个实例可以从不同的配置文件、键值存储等读取。Viper 包支持的所有函数都在 Viper 实例上有对应的方法。
示例:
x := viper.New() y := viper.New() x.SetDefault("ContentDir", "content") y.SetDefault("ContentDir", "foobar") //...
在使用多个 Viper 实例时,用户需要自行跟踪不同的 Viper 实例。
答:Viper 被设计为 Cobra 的伴侣。虽然两者都可以完全独立运行,但它们结合在一起形成了一个强大的组合,可以处理你的应用程序基础需求的大部分内容。
还有比指挥官更好的名字吗?
简而言之: 不支持。
Viper 合并来自各种来源的配置,其中许多要么不区 分大小写,要么使用与其他来源不同的大小写(例如环境变量)。 为了在使用多个来源时提供最佳体验,我们决定使所有键不区分大小写。
曾经有几次尝试实现区分大小写的功能,但不幸的是,这并不那么简单。我们可能会在 Viper v2 中尝试实现它,但尽管最初有些声音,但似乎并没有太多人要求这个功能。
你可以通过填写此反馈表来为区分大小写投票:https://forms.gle/R6faU74qPRPAzchZ9
不,你需要自己同步对 Viper 的访问(例如使用 sync
包)。并发读写可能会导致 panic。
请参阅 TROUBLESHOOTING.md。
为了获得最佳的开发者体验,建议安装 Nix 和 direnv。
或者,在你的计算机上安装 Go,然后运行 make deps
安装其余依赖项。
运行测试套件:
make test
运行代码检查器:
make lint # 使用 -j 选项并行运行
某些代码检查问题可以自动修复:
make fmt
该项目采用 MIT 许可证。
AI数字人视频创作平台
Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。
一站式AI创作平台
提供 AI 驱动的图片、视频生成及数字人等功能,助力创意创作
AI办公助手,复杂任务高效处理
AI办公助手,复杂任务高效处理。办公效率低?扣子空间AI助手支持播客生成、PPT制作、网页开发及报告写作,覆盖科研、商业、舆情等领域的专家Agent 7x24小时响应,生活工作无缝切换,提升50%效率!
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号