zhengduimen 发表于 2024-8-30 17:04

基于python文案转语音并输出-自媒体等职业副业均可使用,不受他人限制

本帖最后由 zhengduimen 于 2024-9-4 17:23 编辑

开发背景:
目前自媒体比较火爆,有很多书单、视频等推广方式可以作为副业盈利,之前每次搞的时候都需要不停的网上找一些在线文字转语音的平台将文案复制上去然后生成下载,好多还是付费的,挺无奈的,然后就想着自己能不能搞,然后的然后就有了下面的东西

先看效果:

代码:
# -*- coding: utf-8 -*-
import asyncio
import os
from edge_tts import Communicate
import time
# 调用合并视频和音频的函数 这个函数自用的 非官方 用于合成音视频 该脚本并不需要此函数 因此注释掉
#import mergeVideoAndVoice
from tqdm import tqdm# 引入 tqdm 库用于显示进度条
#检测输入值
def get_non_empty_input(prompt):
    """
    获取用户输入的非空字符串,若输入为空则提示用户重新输入。
    """
    while True:
      value = input(prompt).strip()
      if value:
            return value
      else:
            print("输入不能为空,请重新输入。")
#文字转语音方法
async def text_to_speech(text, title, voice, voice_dir):
    try:
      beginTime = time.time()
      communicate = Communicate(text, voice)
      endTime = time.time()
      temp_audio_file = os.path.join(voice_dir, f"{title}.mp3.temp")
      # 计算耗时
      elapsedTime = endTime - beginTime
      # 打印耗时
      print(f"耗时: {elapsedTime} 秒")
      #进度条开始前记录下时间
      beginProceTime = time.time()
      formatted_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(beginProceTime))
      print(f"进度条开始: {formatted_time}")
      # 使用 tqdm 创建进度条
      with tqdm(total=100, desc="音频生成进度") as pbar:
            # 运行并等待语音合成完成并保存到临时文件
            await communicate.save(temp_audio_file)
            # 模拟进度更新
            for i in range(100):
                await asyncio.sleep(0.1)# 模拟耗时操作
                pbar.update(1)
                # print(f"当前进度:{i}")
                if i == 99:
                  endProceTime = time.time()
                  formatted_time_end = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(endProceTime))
                  print(f"进度条结束: {formatted_time_end} 秒")
                  proceTime = endProceTime - beginProceTime
                  print(f"总耗时: {proceTime} 秒")

      final_audio_file = os.path.join(voice_dir, f"{title}.mp3")
      os.rename(temp_audio_file, final_audio_file)
      return final_audio_file
    except Exception as e:
      # 处理异常
      print(f"生成音频文件时发生错误: {e}")
      return None

async def main(videoRealPath, videoRealName, text):
    isNeedInput = get_non_empty_input("请确认音频保存路径是否需要输入 Y:需要 N:不需要 (不需要输入请确认脚本路径配置正确):")
    print("视频完整路径:" + videoRealPath + " 视频名称:" + videoRealName + " 文案:" + text)
    title = videoRealName
    voice_options = {
      '1': 'zh-CN-XiaoxiaoNeural',         # 晓晓,女性
      '2': 'zh-CN-YunxiNeural',            # 云希,男性
      '3': 'zh-CN-YunyangNeural',          # 云扬,男性
      '4': 'zh-CN-YunjianNeural',          # 云健,男性
      '5': 'zh-CN-XiaoyiNeural',         # 晓忆,女性
      '6': 'zh-CN-XiaohanNeural',          # 晓涵,女性
      '7': 'zh-CN-XiaomengNeural',         # 晓萌,女性
      '8': 'zh-CN-XiaomoNeural',         # 晓墨,女性
      '9': 'zh-CN-XiaoqiuNeural',          # 晓秋,女性
      '10': 'zh-CN-XiaoruiNeural',         # 晓睿,女性
      '11': 'zh-CN-XiaoshuangNeural',      # 晓霜,女性
      '12': 'zh-CN-XiaoyanNeural',         # 晓颜,女性
      '13': 'zh-CN-XiaoyouNeural',         # 晓悠,女性
      '14': 'zh-CN-XiaoyuMultilingualNeural', # 晓宇,多语言
      '15': 'zh-CN-XiaozhenNeural',      # 晓真,女性
      '16': 'zh-CN-YunfengNeural',         # 云风,男性
      '17': 'zh-CN-YunhaoNeural',          # 云浩,男性
      '18': 'zh-CN-YunjieNeural',          # 云杰,男性
      '19': 'zh-CN-YunxiaNeural',          # 云霞,男性
      '20': 'zh-CN-YunyeNeural',         # 云野,男性
      '21': 'zh-CN-YunyiMultilingualNeural', # 云一,多语言
      '22': 'zh-CN-YunzeNeural',         # 云泽,男性
      '23': 'zh-CN-YunfanMultilingualNeural', # 云凡,多语言
      '24': 'zh-CN-YunxiaoMultilingualNeural', # 云晓,多语言
      '25': 'zh-CN-XiaochenMultilingualNeural', # 晓晨,多语言
      '26': 'zh-CN-XiaoxiaoDialectsNeural',# 晓晓,方言
      '27': 'zh-CN-XiaoxiaoMultilingualNeural', # 晓晓,多语言
      '28': 'zh-CN-XiaoyuMultilingualNeural',# 晓宇,多语言
      '29': 'zh-CN-XiaobeiNeural',          # 晓北,女性
      '30': 'zh-CN-guangxi-YunqiNeural1.3', # 广西,云奇,男性
      '31': 'zh-CN-henan-YundengNeural3',   # 河南,云登,男性
      '32': 'zh-CN-liaoning-XiaobeiNeural1.3', # 辽宁,晓北,女性
      '33': 'zh-CN-liaoning-YunbiaoNeural1.3', # 辽宁,云彪,男性
      '34': 'zh-CN-shaanxi-XiaoniNeural1.3', # 陕西,晓妮,女性
      '35': 'zh-CN-shandong-YunxiangNeural3', # 山东,云翔,男性
      '36': 'zh-CN-sichuan-YunxiNeural1.3', # 四川,云希,男性
      '37': 'zh-HK-HiuMaanNeural',          # 香港,晓曼,女性
      '38': 'zh-HK-WanLungNeural',          # 香港,云龙,男性
      '39': 'zh-HK-HiuGaaiNeural',          # 香港,晓佳,女性
      '40': 'zh-TW-HsiaoChenNeural',      # 台湾,晓晨,女性
      '41': 'zh-TW-YunJheNeural',         # 台湾,云哲,男性
      '42': 'zh-TW-HsiaoYuNeural'         # 台湾,晓宇,女性
    }
    for key, value in voice_options.items():
      print(f"{key}: {value}")
    voice_choice = get_non_empty_input("请输入语音音色的编号: ")
    voice = voice_options.get(voice_choice, 'zh-CN-YunxiNeural')# 使用默认音色或用户选择的音色
    if isNeedInput in ("Y", "y"):
      voice_dir = get_non_empty_input("请输入音频保存路径:")
    else:
      voice_dir = "/Users/ljj/Documents/mayun/video/voice"
    if not os.path.exists(voice_dir):
      print("音频保存路径不存在,创建并使用")
      os.makedirs(voice_dir)

    # 使用 edge-tts 生成音频文件
    audio_file = await text_to_speech(text, title,voice,voice_dir)
    if audio_file is None:
      print("音频文件生成失败,等待 10 秒后重试")
      await asyncio.sleep(10)
      for retry_count in range(3):# 重试 3 次
            audio_file = await text_to_speech(text, title, voice, voice_dir)
            if audio_file:
                break
            print(f"重试 {retry_count + 1} 次失败,等待 5 秒后继续")
            await asyncio.sleep(5)
   # 如果音频文件生成成功并且大小符合要求
    if audio_file and os.path.getsize(audio_file) > 1024:# 例如,检查文件大小是否大于 1KB
      mergeVideoAndVoice.main(videoRealPath, audio_file, videoRealName)
    else:
      print("音频文件过小或生成失败,等待后重试")
      await asyncio.sleep(5)# 等待一段时间后重试
      if audio_file and os.path.getsize(audio_file) > 1024:
            mergeVideoAndVoice.main(videoRealPath, audio_file, videoRealName)
   
if __name__ == "__main__":
    isNeedInput = get_non_empty_input("请确认是否需要输入 Y:需要 N:不需要 (不需要输入请确认脚本路径配置正确):")
    isAuto = get_non_empty_input("是否全模型自动生成 Y:需要 N:不需要:")
    if isNeedInput in("Y","y"):
      title = get_non_empty_input("请输入音频标题:")
      text = get_non_empty_input("请输入文案,若文案过长无法再控制台输入请直接将文案在代码中赋值:")
      voice_dir = get_non_empty_input("请输入音频保存完整路径:")
    elif isNeedInput in("N","n"):
      title="测试"
      text='测试语音效果'# 这里是文字转语音的文案,代码中不限制长度 ,但注意控制台赋值粘贴本身有长度限制,如果文案较长,请直接在代码中处理
      voice_dir='/Users/ljj/Documents/mayun/video/voice'# 这里是文字转语音的文案,不限制长度
    else:
      print("输入错误")
      exit()
    # 6~1820~2830 31333536 模型似乎是收费模型 无法使用
    voice_options = {
      '1': 'zh-CN-XiaoxiaoNeural',         # 晓晓,女性
      '2': 'zh-CN-YunxiNeural',            # 云希,男性
      '3': 'zh-CN-YunyangNeural',          # 云扬,男性
      '4': 'zh-CN-YunjianNeural',          # 云健,男性
      '5': 'zh-CN-XiaoyiNeural',         # 晓忆,女性
      '6': 'zh-CN-XiaohanNeural',          # 晓涵,女性
      '7': 'zh-CN-XiaomengNeural',         # 晓萌,女性
      '8': 'zh-CN-XiaomoNeural',         # 晓墨,女性
      '9': 'zh-CN-XiaoqiuNeural',          # 晓秋,女性
      '10': 'zh-CN-XiaoruiNeural',         # 晓睿,女性
      '11': 'zh-CN-XiaoshuangNeural',      # 晓霜,女性
      '12': 'zh-CN-XiaoyanNeural',         # 晓颜,女性
      '13': 'zh-CN-XiaoyouNeural',         # 晓悠,女性
      '14': 'zh-CN-XiaoyuMultilingualNeural', # 晓宇,多语言
      '15': 'zh-CN-XiaozhenNeural',      # 晓真,女性
      '16': 'zh-CN-YunfengNeural',         # 云风,男性
      '17': 'zh-CN-YunhaoNeural',          # 云浩,男性
      '18': 'zh-CN-YunjieNeural',          # 云杰,男性
      '19': 'zh-CN-YunxiaNeural',          # 云霞,男性
      '20': 'zh-CN-YunyeNeural',         # 云野,男性
      '21': 'zh-CN-YunyiMultilingualNeural', # 云一,多语言
      '22': 'zh-CN-YunzeNeural',         # 云泽,男性
      '23': 'zh-CN-YunfanMultilingualNeural', # 云凡,多语言
      '24': 'zh-CN-YunxiaoMultilingualNeural', # 云晓,多语言
      '25': 'zh-CN-XiaochenMultilingualNeural', # 晓晨,多语言
      '26': 'zh-CN-XiaoxiaoDialectsNeural',# 晓晓,方言
      '27': 'zh-CN-XiaoxiaoMultilingualNeural', # 晓晓,多语言
      '28': 'zh-CN-XiaoyuMultilingualNeural',# 晓宇,多语言
      '29': 'zh-CN-XiaobeiNeural',          # 晓北,女性
      '30': 'zh-CN-guangxi-YunqiNeural', # 广西,云奇,男性
      '31': 'zh-CN-henan-YundengNeural',   # 河南,云登,男性
      '32': 'zh-CN-liaoning-XiaobeiNeural', # 辽宁,晓北,女性
      '33': 'zh-CN-liaoning-YunbiaoNeural', # 辽宁,云彪,男性
      '34': 'zh-CN-shaanxi-XiaoniNeural', # 陕西,晓妮,女性
      '35': 'zh-CN-shandong-YunxiangNeural', # 山东,云翔,男性
      '36': 'zh-CN-sichuan-YunxiNeural', # 四川,云希,男性
      '37': 'zh-HK-HiuMaanNeural',          # 香港,晓曼,女性
      '38': 'zh-HK-WanLungNeural',          # 香港,云龙,男性
      '39': 'zh-HK-HiuGaaiNeural',          # 香港,晓佳,女性
      '40': 'zh-TW-HsiaoChenNeural',      # 台湾,晓晨,女性
      '41': 'zh-TW-YunJheNeural',         # 台湾,云哲,男性
      '42': 'zh-TW-HsiaoYuNeural'         # 台湾,晓宇,女性
    }
    #这里是循环自动生成 - 看那个语音好听x>=6   x<=18x>=20x<=28 不可用 估计是语音平台收费的 其余应该是属于开源可用的,没那时间去接入了 剩下这么多 够用了
    if isAuto in("Y","y"):
      for key, value in voice_options.items():
            lastTitle = title+"_"+key
            voice = value
            print("")
            print(f"第{key}: {value}模型正在初始化处理功能,请稍等...")
            asyncio.run(text_to_speech(text,lastTitle,voice, voice_dir))
    else:
      # 这里是手动选择生成
      for key, value in voice_options.items():
            print(f"{key}: {value}")
      voice_choice = get_non_empty_input("请输入语音音色的编号: ")
      title = title+"_"+voice_choice
      voice = voice_options.get(voice_choice, 'zh-CN-YunxiNeural')# 使用默认音色或用户选择的音色
      print("正在初始化处理功能,请稍等...")
      asyncio.run(text_to_speech(text, title,voice, voice_dir))
   
   



代码内部需要的库请自行下载,注意当文案内容过长时,由于控制台输入限制会出现缺失,建议直接改代码,将文案复制进去然后执行生成。


阿里网盘 分享链接,设置的无提取码,永不过期如果网盘没动的话,我自己是不会动的,内含 mac 端 可执行文件 和win 端可执行文件:
文字转语音
https://www.alipan.com/s/XkGNHxVP39F
点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。

textToVoice.exewin端执行 - 安装杀毒软件会报毒,代码就是上边帖子发的那些代码,不放心的自己打个包完事。
textToVoiceMacmac 端执行 - 我自己这边是可以运行的 但是找了俩人 试了下 都说不行,不知道啥情况 {:1_907:}{:1_907:}{:1_907:}-- 因为是微信发的 怀疑是被微信给改了格式了--- 确认了 就是微信改格式了。执行程序 变 文稿了
注意:控制台输入字数有上限要求,还是用直接用代码比较合适,代码我试过小说一章节内容执行转换没问题,---- 控制台就比较感人了   试试看行不行

lj149446 发表于 2024-10-12 09:59

楼主你做的啥啊,几个字半天转不出来哟 试试我的
import requests
import edge_tts
import os
import asyncio
import pygame
import time

'''
播音员:

zh-CN-YunyangNeural 新闻主播 | zh-CN-YunxiNeural 网红男音

zh-CN-XiaoyiNeural少女主播 | zh-CN-XiaoxiaoNeural 小小

'''
TEXT = ""
file_path = 'ci.txt'
output_filename = '文件转语音.mp3'

with open(file_path, 'rb') as f:
    data = f.read()
    # 尝试不同的编码格式
    encoding_options = ['utf-8', 'gbk']
    for encoding in encoding_options:
      try:
            TEXT = data.decode(encoding=encoding)
            break
      except UnicodeDecodeError:
            continue
    #如果有符号读音,可以把替换的符号加入列表
    symbols = ['*', '#', '_']
    for symbol in symbols:
      TEXT = TEXT.replace(symbol, '')
   
    #主播
    voice = 'zh-CN-XiaoyiNeural'
    output = os.path.join(os.getcwd(), output_filename)
    #语速
    rate = '-10%'
    #音量
    volume = '+40%'

    async def my_function():
      tts = edge_tts.Communicate(text=TEXT, voice=voice, rate=rate, volume=volume)
      await tts.save(output)

    asyncio.run(my_function())

    while not os.path.exists(output):
      pass

    pygame.init()
    pygame.mixer.init()
    pygame.mixer.music.load(output)
    pygame.mixer.music.play()
    while pygame.mixer.music.get_busy():
      pygame.time.Clock().tick(10)
    pygame.mixer.music.unload()

zhengduimen 发表于 2024-9-4 15:51

本帖最后由 zhengduimen 于 2024-9-4 16:19 编辑

sondycnc 发表于 2024-9-4 11:58
那不简单,再新生成一个WINDOWS的呗
阿里网盘 分享链接,设置的无提取码,永不过期如果网盘没动的话,我自己是不会动的,内含 mac 端 可执行文件 和win 端可执行文件:
文字转语音
https://www.alipan.com/s/XkGNHxVP39F
点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。

textToVoice.exewin端执行 - 安装杀毒软件会报毒,代码就是上边帖子发的那些代码,不放心的自己打个包完事。
textToVoiceMacmac 端执行
注意:控制台输入字数有上限要求,还是用直接用代码比较合适,代码我试过小说一章节内容执行转换没问题,---- 控制台就比较感人了   试试看行不行

JackChen1688 发表于 2024-8-31 08:47

感觉还行下载下来看看

JackChen1688 发表于 2024-8-31 09:15

我想问下lz这个 mergeVideoAndVoice 是什么

JackChen1688 发表于 2024-8-31 09:17

噢,代码没贴完啊,还说来看看效果呢

zhengduimen 发表于 2024-8-31 13:43

JackChen1688 发表于 2024-8-31 09:17
噢,代码没贴完啊,还说来看看效果呢

那个没用 干掉就行 你说的那个脚本是我用来合成视频的 跟文案转语音没关系。

zhengduimen 发表于 2024-8-31 13:44

JackChen1688 发表于 2024-8-31 09:15
我想问下lz这个 mergeVideoAndVoice 是什么

看名字应该能理解它是干嘛的吧 mergevideoandvoice

ericwise 发表于 2024-8-31 17:45

JackChen1688 发表于 2024-8-31 09:15
我想问下lz这个 mergeVideoAndVoice 是什么

合并视频及语音

zhengduimen 发表于 2024-9-2 08:44

# 调用合并视频和音频的函数
import mergeVideoAndVoice   这个脚本注释掉 这是合成本地音视频用的 原因是我视频处理完成后 在调用完 文案转语音之后要合成输出视频并保存

easy2003 发表于 2024-9-2 09:02

请教一下,ModuleNotFoundError: No module named 'mergeVideoAndVoice',官方找不到这个mergeVideoAndVoice模块

zhengduimen 发表于 2024-9-2 09:03

本帖最后由 zhengduimen 于 2024-9-2 09:05 编辑

easy2003 发表于 2024-9-2 09:02
请教一下,ModuleNotFoundError: No module named 'mergeVideoAndVoice',官方找不到这个mergeVideoAndVoic ...
mergeVideoAndVoice   这个注释掉这个是另一个脚本 不涉及 语音生成

已经注释掉了 在等待审核

# 调用合并视频和音频的函数 这个函数自用的 非官方 用于合成音视频 该脚本并不需要此函数 因此注释掉
#import mergeVideoAndVoice
页: [1] 2 3 4 5 6
查看完整版本: 基于python文案转语音并输出-自媒体等职业副业均可使用,不受他人限制