C#基于BaiduAI做的二次开发的语音合成Wpf应用程序

基于baiduAI完成的一个语音合成小程序使用的是Wpf做的界面后台C# .Net4.0工具Vsual Studio2017
只是其他功能也可以这样开发不过得先注册一个Baidu账号 在BaiduAI首页点击产品服务找到语音识别点击使用即可注册应用将几个Key值填入程序即可也可以做成从config读取都行 做的有些地方确实有漏洞不过大体功能都实现了 1.开发BaiduAI需要从NuGet中安装baiduai组件顺带安装Newtonsoft.Json.dll组件 2.页面代码

<Window x:Class="语音合成.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:语音合成"
        mc:Ignorable="d"
        Background="Transparent"
        AllowsTransparency="True"
        WindowStyle="None"
        Title="MainWindow" Height="450" Width="300" MaxHeight="450" MaxWidth="300" MinHeight="450" MinWidth="300"
        //MouseLeftButtonDown事件用于移动没有样式之后的windows窗体
        MouseLeftButtonDown="Window_MouseLeftButtonDown" Icon="ico/sound.png">
    <Window.Resources>//存放样式
        //关闭按钮的样式
        <!--Btn_Close_style_Start-->
        <Style x:Key="Btn_Close_style" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Image Name="btncl" Source="ico/close.png" />
                        <ControlTemplate.Triggers>
                        //触发器用于改善Button加图后鼠标放上变白的情况
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Source"  Value="ico/mclose.png" TargetName="btncl"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!--Btn_Close_style_End-->
        //播放按钮的样式
        <!--Btn_Play_style_Start-->
        <Style x:Key="Btn_Play_style" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Image Width="45" Name="btncl" Source="ico/play.png"/>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Source"  Value="ico/mplay.png" TargetName="btncl"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!--Btn_Play_style_End-->
        //播放按钮停止后的样式
        <!--Btn_Pause_style_Start-->
        <Style x:Key="Btn_Pause_style" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Image Width="45" Name="btncl" Source="ico/pause.png"/>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Source"  Value="ico/mpause.png" TargetName="btncl"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!--Btn_Pause_style_End-->
        //上传处理按钮的样式
        <!--Btn_Upload_style_Start-->
        <Style x:Key="Btn_Upload_style" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Image Width="45" Name="btncl" Source="ico/upload.png"/>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Source"  Value="ico/mupload.png" TargetName="btncl"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!--Btn_Upload_style_End-->
        //上传处理按钮的样式将样式反转可以明显看出是否在上传
        <!--Btn_Back_Upload_style_Start-->
        <Style x:Key="Btn_Back_Upload_style" TargetType="{x:Type Button}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Image Width="45" Name="btncl" Source="ico/mupload.png"/>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="true">
                                <Setter Property="Source"  Value="ico/upload.png" TargetName="btncl"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <!--Btn_Back_Upload_style_End-->
        //textBox公共样式文件
        <!--Tb_style_Start-->
        <Style TargetType="TextBox">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Margin" Value="4,0"/>
        </Style>
        <!--Tb_style_End-->
        //特定的几个Broader美化标签的样式
        <!--Br_style_Start-->
        <Style x:Key="Br_style" TargetType="Border">
            <Setter Property="CornerRadius" Value="5"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="#FF2E2525"/>
            <Setter Property="Margin" Value="5,2"/>
        </Style>
        <!--Br_style_End-->
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="350"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        //背景美化
        <Border BorderThickness="1" BorderBrush="Gray"  CornerRadius="10"  Grid.ColumnSpan="2" Grid.RowSpan=">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF7AB0C9" Offset="0"/>
                    <GradientStop Color="#FF6767A0" Offset="0.996"/>
                    <GradientStop Color="#FF828282" Offset="0.51"/>
                    <GradientStop Color="#FF6BC3AF" Offset="0.151"/>
                </LinearGradientBrush>
            </Border.Background>
        </Border>
        //图标
        <Image Source="ico/sound.png" Margin="10,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left"/>
        //Title
        <Label Content="语音合成"  HorizontalAlignment="Center" Margin="4,0,0,0" VerticalContentAlignment="Center" FontSize="16" Grid.Row="0" Grid.Column="0" FontFamily="Tahoma"/>
        //Close_Button
        <Button Style="{DynamicResource  Btn_Close_style}" Name="Btn_Close" Click="Button_Click"  Margin="10,5" Width="20" Grid.Column="1" HorizontalAlignment="Right" />
        //Title_TextBox
        <Border Style="{StaticResource Br_style}" Background="Transparent" Grid.Row="1" Grid.ColumnSpan="2">
            <TextBox Name="TB_title" Height="25" FontSize="20"/>
        </Border>
        //Content_TextBox
        <Border Style="{StaticResource Br_style}" Grid.Row="2" Grid.ColumnSpan="2">
            <TextBox Name="TB_content" Text="拖入txt文件即可使用" FontSize="16" AllowDrop="True" PreviewDragOver="TB_content_Drop" TextWrapping="Wrap" UndoLimit="96"/>
        </Border>
        //播放Button并将上面的样式置入
        <Button Style="{DynamicResource Btn_Play_style}" Name="Btn_Sound" Grid.Row="3" Margin="5" Click="Btn_Sound_Click" IsEnabled="False"/>
        //上传
        <Button Style="{DynamicResource Btn_Upload_style}" Name="Btn_Upload" Grid.Row="3" Grid.Column="1" Margin="5" Background="Black" Click="Btn_Upload_Click"/>
        //下面两个分别是缓冲圈和提示操作错误用的
        <Image Name="Img_Buffer" Source="ico/current.png" Width="24" Height="24" Grid.Row="2" Grid.ColumnSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="Collapsed"/>
        <Label Name="Lab_Prompt" Width="140" Height="40" Background="Transparent" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Content="请拉入txt文件" Visibility="Collapsed" Grid.Row="2" Grid.ColumnSpan="2" FontSize="20" Foreground="#FF9E2626" AllowDrop="True" PreviewDragOver="TB_content_Drop"/>
    </Grid>
</Window>

3.后台代码(全部写在了一起)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Baidu.Aip.Speech;

namespace 语音合成
{

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        //判断是否在播放
        public bool IsSound { get; set; } = false;
        //判断是否在上传用于控制缓冲圈和控件的开启关闭
        public bool IsUpload { get; set; } = false;
        //BaiduAI重要的三个属性App_ID,API_Key,SECRET_KEY用于生成token可以通过创建软件获取
        public string APP_ID { get; } = "";
        public string API_KEY { get; } = "";
        public string SECRET_KEY { get; } = "";
        //用于播放生成的音频文件
        MediaPlayer player = new MediaPlayer();
        //用于存放内容
        string conetnt;
        //存放文件地址
        public string Path { get; set; } = "";
        public MainWindow()
        {
            InitializeComponent();
        }
        //实现拖拽窗口的事件
        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
                this.DragMove();
        }
        //关闭
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
        //播放
        private void Btn_Sound_Click(object sender, RoutedEventArgs e)
        {
            //判断是否播放了播放就暂停
            if (IsSound)
            {
                if (player.CanPause)
                    player.Pause();
                Btn_Sound.Style = (Style)this.FindResource("Btn_Play_style");
            }
            else
            {
                if (Path != "")
                {
                    //添加播放完成事件
                    player.MediaEnded += Play_stop_Event;
                    player.Play();
                }
                Btn_Sound.Style = (Style)this.FindResource("Btn_Pause_style");
            }
            IsSound = !IsSound;

        }
        //播放完成后改回样式
        private void Play_stop_Event(object sender, EventArgs e)
        {
            Btn_Sound.Style = (Style)this.FindResource("Btn_Play_style");
            IsSound = false;
        }
        //上传
        private void Btn_Upload_Click(object sender, RoutedEventArgs e)
        {
            //将前端控件样式进行更改体现出正在对文本文件进行处理
            Lab_Prompt.Visibility = Visibility.Collapsed;
            Btn_Upload.Style = (Style)this.FindResource("Btn_Back_Upload_style");
            IsUpload = true;
            Btn_Upload.IsEnabled = false;
            Img_Buffer.Visibility = Visibility.Visible;
            TB_content.IsEnabled = false;
            //生成token
            var client = new Tts(API_KEY, SECRET_KEY);
            //设置多少延时之后未成功算失败
            client.Timeout = 60000;
            //初始化一个旋转属性并设置旋转中心(这里的缓冲图片设置的是24*24)
            RotateTransform rotate = new RotateTransform()
            {
                CenterX = 12,
                CenterY = 12
            };
            //获取内容
            conetnt = TB_content.Text;
            //获取长度
            int leng = conetnt.Length;
            //由于最大上传文件为1024B所以直接以500个字符为分段进行截取防止意外
            int cs = leng/ 500;
            //用于判断有没有多出的字符
            int ys = leng % 500;
            //有的话就对循环次数进行+1
            cs = ys == 0 ? cs : cs+1;
            new Thread(() =>
            {   
                //设置基本返回信息(还有语调等可以设置看需求进行添加调试)
                var option = new Dictionary<string, object>()
                    {
                    {"spd", 4}, // 语速
                    {"vol", 9}, // 音量
                    {"per", 0}  // 发音人
                        };
                //判断输入的是文件还是个人输入如果是就在D盘生成
                Path = Path == "" ? "D:\\yuyin.mp3" : $"{ Path}.mp3";
                //先进行一个连同测试测试与服务器连通是否正常
                var result = client.Synthesis(conetnt[0].ToString(), option);
                //创建数组存放返回文件
                byte[] mic= { };
                for (int i = 0; i < cs; i++)
                {
                    //判断连通是否正常
                    if (result.ErrorCode == 0)
                    {
                        //判断字符长度是否小于500小于的话直接发送
                        if(leng>500)
                            //将前面的字符分开发送
                            result = client.Synthesis(conetnt.Substring(i*500,cs-1==i?leng-500:500), option);
                        else
                            result = client.Synthesis(conetnt, option);
                        //用于将返回的Byte[]合并成一个文件
                        byte[] nCon = new byte[mic.Length+ result.Data.Length];   
                        mic.CopyTo(nCon,0)   ; 
                        result.Data.CopyTo(nCon,mic.Length);
                        mic = nCon;
                    }
                    else
                    {
                        //如果出错则显示生成错误
                        this.Dispatcher.Invoke(new Action(() =>
                        {
                            Lab_Prompt.Visibility = Visibility.Visible;
                            Lab_Prompt.Content = "生成错误";
                            IsUpload = false;
                            return;
                        }));
                    }
                }
                //将Byte[]保存
                File.WriteAllBytes(Path, mic);
                //将音频文件加载到MediaPlayer类中用于播放
                this.Dispatcher.Invoke(new Action(() =>
                {
                    player.Open(new Uri(Path, UriKind.Absolute));
                    IsUpload = false;
                }));
            })
            { IsBackground = true }.Start();
            //缓冲圈线程
            new Thread(() =>
            {
                int i = 1;
                while (IsUpload)
                {
                    //每十毫秒更新一次ui比较流畅
                    Thread.Sleep(10);
                    if (i >= 360)
                        i = 1;
                    //每次加5度旋转
                    i += 5;
                    this.Dispatcher.Invoke(new Action(() =>
                    {
                        //参数附加并实现变化
                        rotate.Angle = i;
                        Img_Buffer.RenderTransform = rotate;
                    }));
                }
                this.Dispatcher.Invoke(new Action(() =>
                {
                    //缓冲圈结束后将控件解锁和恢复
                    Img_Buffer.Visibility = Visibility.Collapsed;
                    Btn_Upload.Style = (Style)this.FindResource("Btn_Upload_style");
                    Btn_Upload.IsEnabled = true;
                    TB_content.IsEnabled = true;
                    Btn_Sound.IsEnabled = true;
                }));
            })
            { IsBackground = true }.Start();
        }
        //文件拖入大实现使用的是DropOver事件
        private void TB_content_Drop(object sender, DragEventArgs e)
        {
            Lab_Prompt.Visibility = Visibility.Collapsed;
            string msg = "Drop";
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                msg = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
            }
            string[] msgs = msg.Split('.');
            //截取后缀判断是否符合要求不符合
            if (msgs[msgs.Length-1] == "txt")
            {
                Path = msg;
                TB_title.Text = Path;
                TB_content.Text =File.ReadAllText(Path,Encoding.Default);
                return;
            }
            Lab_Prompt.Content=“请放入txt文件”;
            Lab_Prompt.Visibility = Visibility.Visible;
        }
    }
}

转载于:https://my.oschina.net/u/3264446/blog/1842024

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值