py实现有声翻译

gitcode开源https://gitcode.net/weixin_46665865/python_demo/-/blob/master/%E8%87%AA%E5%B7%B1write/%E6%9C%89%E5%A3%B0%E7%BF%BB%E8%AF%91.py

有些翻译软件太大了,我这拉胯电脑不允许,打开idea就很卡了,但是idea的一个翻译插件(微软接口,其他的要API 上次试了百度的也不行)不能出声,只能翻译,就很烦,所以就想自己写一个,单词,声音很容易,就在句子的翻译就搞的很心累,最后还是搞定了,嗨·

我就可以不用打开,直接用py文件(音频文件会创建文件夹不会自动删)双击打开,很快的方法就是发送快捷方式到桌面,然后在快捷方式里面的属性设置快捷键,就能直接打开了,我刚好有个快捷打开的软件Lucy,把py拖进去在里面设置快捷键很快速。我就可以先复制在快捷键就马上启动了

# By:仰晨
# 文件名:有声翻译
# 时 间:2023/2/23 22:20----真tm的够了2.24 2:51明天早课----
#            2.24 15:30----tm的还得是360翻译----16:31tm的多行不行就搞剪贴板---
#            3.05 22:24----大优化cmd窗口+esc关闭&输入其他英语继续翻译&判断如果剪贴板文字为空就让自行输入&其他小优化
#            3.12 16:04----剪贴板内容if包含驼峰命名then拆分成多个单词
#                 16:23----音频文件不缓存了,删掉了1️⃣文件名字方法2️⃣专门多线程播放声音的方法3️⃣去除为缓存文件创建一个文件夹设置为工作路径
#            3.19 04:06----有时候翻译很长的自动播放音频好吵,如果太长了刚开始就不读了按0再读,短的还是自动播放
#                 23:57----判断剪贴板字符串是否包涵英文字母,不存在就重新输入(之前是为空才重新输入,(为空也是不包含英文))
#            3.20 00:12----剪贴板内容if包涵下划线就替换为空格
#            3.22 18:29----引入读文本库读句子,单词声音还是百度取 18:36 剪贴板的.也换为空格
#            6.19 03:22----解决用网络代理就闪退问题
#            6.19 09:37----明确不用代理
#            7.15 14:13----优化:把多个连续的空格变成一个   .后面不为空白字符的.变成空格   导入URL编码(之前剪贴板多行有bug)
#                 15:10----优化:加颜色
#            8.14 21:55----优化:cmd窗口按esc秒关,在pycharm也能秒关,但是没输入回车关闭响应慢了0.几秒


import re

import pyperclip  # 读取剪贴板
import requests

# 播放声音
from io import BytesIO
import sounddevice as sd
import soundfile as sf

# 读文字出声音模块
import pyttsx3

# 监控esc键按了就结束
import threading
from pynput import keyboard
import time

from urllib.parse import quote_plus  # URL编码
from colorama import Fore, Style, init, Back  # 输出颜色

# 初始化colorama,使其在所有支持的平台上都能使用彩色输出
init()  # pycharm不需要,cmd才要

# 使用网络出海会报错所以要明确不要代理
proxies = {
    'http': None,
    'https': None,
}


# 监控esc键,按下就报错
def on_press(key):
    # 检测ESC键是否被按下
    if key == keyboard.Key.esc:
        print("检测ESC键是否被按下 或者 翻译线程结束了...触发系统退出")
        # 触发系统退出
        # raise SystemExit(0)
        raise "你干嘛哎呦"

    # 线程数=2(主线程 翻译线程 监控线程 少了就是不行了,不然按回车监控线程还一直运行)
    time.sleep(0.5)
    if threading.active_count() == 2:
        0/0


# 把英语声音拿到内存 并调用播放   如果太长了刚开始就不读了按0再读
def sound(word):
    mp3 = None  # 单个单词
    say = True  # 读句子
    play_one = False  # 超长第一次?
    engine = pyttsx3.init()  # 初始化语音引擎
    if re.match(r'^[a-zA-Z]+$', word):
        try:
            mp3 = BytesIO(requests.get(f"https://fanyi.baidu.com/gettts?lan=en&text={word}&spd=3&source=web").content)
            say = False  # (非全字母)
        except Exception:
            pass

    while True:
        printf = "——————输入0重新播放音频,直接回车或esc退出,输入其他英语继续翻译——————\n"
        if say:  # 是否是句子
            # print("是句子 启动本地引擎")
            if play_one or word.count(" ") < 6:  # 包涵6个空格表示很长就第一次不读
                # 使用语音引擎朗读文本
                engine.say(word)
                # 运行语音引擎,等待文本朗读完成
                engine.runAndWait()
            else:
                play_one = True
                printf = "——————该句太长 想播放请按0,直接回车或esc退出,输入其他英语继续翻译——————\n"
        else:
            try:
                # print("是单词 启动百度引擎")
                mp3.seek(0)  # 将指针重置为数据的开头
                samples, fs = sf.read(mp3, dtype='float32')
                sd.play(samples, fs)
            except:
                print("********获取不到网络声音,读本地的********")
                # 使用语音引擎朗读文本
                engine.say(word)
                # 运行语音引擎,等待文本朗读完成
                engine.runAndWait()

        print(Back.BLUE + Fore.WHITE + Style.BRIGHT)
        input_why = input(printf)
        print(Style.RESET_ALL)

        if input_why != '0':
            return input_why


# 显示翻译内容
def show_word(e):
    # 显示单词
    print("翻译结果为:" + "——" * 18)
    print(Fore.GREEN + Style.BRIGHT, end='')
    # print(f"@@@@@@@@@@@@@看看打印出来的是什么?----------------------------------{quote_plus(e)}")

    try:
        print(requests.post("https://fanyi.baidu.com/sug", {"kw": e}, proxies=proxies).json()["data"][0]['v'])
    # 显示句子
    except IndexError:
        try:
            headers = {
                "accept-language": "zh-CN,zh;q=0.9",
                "accept-encoding": "gzip, deflate, br",
                "pro": "fanyi",
                "sec-ch-ua-platform": "Windows",
                "sec-fetch-dest": "empty",
                "ec-fetch-mode": "cors",
                "sec-fetch-site": "same-origin",
                "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                              "Chrome/98.0.4758.139 Safari/537.36",
            }

            print(requests.post(
                url=f"https://fanyi.so.com/index/search?eng=1&validate=&ignore_trans=0&query={quote_plus(e)}",
                headers=headers, proxies=proxies).json()["data"]["fanyi"])

        except IndexError:
            print("-----备用翻译也失败了-----")


def main(english1=""):
    # 显示翻译内容
    show_word(english1)
    # threading.Thread(target=show_word, args=(english1,)).start()  # 多线程但不喜欢排序混乱

    # 输出音频 并返回看看是否继续翻译
    english1 = sound(english1)
    if english1 != "":
        main(english1)


if __name__ == '__main__':
    print("(程序要网,如果尝试几次都没输出翻译 那就是翻译api出现问题)剪贴板内容if包含驼峰命名then拆分成多个单词 包涵_就变成空格\n所以想翻译驼峰命名的或者下划线的要重新贴")
    print("《优点:单个单词能有多个结果,短句自动播放音频,长句按0再播放 \n《缺点:本程序只有英文翻译为中文(中文翻译英文只有词可以),短的单词声音也必定播放")
    print("***运行前先复制要翻译的值到剪贴板,运行时会自动获取剪贴板的值进行翻译***")
    # 读取剪贴板内容  包含驼峰命名的就拆分成多个单词,包涵下划线就替换为空格 否则就按原来的输出
    english = re.sub(r'(?<=[^A-Z\s])([A-Z])', r' \1', pyperclip.paste()).replace('_', ' ')
    # 把多个连续的空格变成一个
    english = re.sub(r' +', ' ', english)
    # .后面不为空白字符的.变成空格
    english = re.sub(r'\.(?!\s)', ' ', english)
    print("——" * 20)
    if not bool(re.search(r'[a-zA-Z]', english)):
        english = input("剪贴板内容不包含english,请先输入英文吧~")  # 没办法处理多行的,因为回车就向下执行了
    else:
        print("剪贴板内容为:" + Fore.YELLOW + english)
        print(Style.RESET_ALL, end="")

    # 创建用户输入的线程
    input_thread = threading.Thread(target=main, daemon=True, args={english})
    input_thread.start()

    # 创建键盘监听器--直到按esc结束
    with keyboard.Listener(on_press=on_press) as listener:
        listener.join()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值