1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自作リアルタイム翻訳ツール

Posted at

はじめに、この小さなツールの由来について話しましょう。私は11月16日に東京で「AI応用開発の旅」というコミュニティイベントを開催する予定です(https://www.just-agi.com/event.html)。主に中国人向けのイベントなので中国語を使用しますが、友人が日本人を連れてくる予定で、日本語の字幕があるかどうか聞かれました。Teamsを見てみたところ、リアルタイム字幕はあるものの翻訳はありませんでしたので、自分でツールを作ることにしました。

 このツールはWinFormで開発されており、源言語と翻訳後のテキストのみを表示し、その他の部分は透明化しています。リアルタイム翻訳にはMicrosoft Speechの翻訳APIを利用しており、開発には10分ほどしかかからなかったです。

MainForm.Designer.cs ファイル:

namespace JapneseHelper
{
    partial class MainForm
    {
        /// <summary>
        ///  Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        ///  Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        ///  Required method for Designer support - do not modify
        ///  the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            ZhLab = new Label();
            JaLab = new Label();
            SuspendLayout();
            // 
            // ZhLab
            // 
            ZhLab.BackColor = Color.Transparent;
            ZhLab.Dock = DockStyle.Bottom;
            ZhLab.Font = new Font("Microsoft YaHei UI", 24F);
            ZhLab.ForeColor = Color.White;
            ZhLab.Location = new Point(0, 530);
            ZhLab.Margin = new Padding(5, 0, 5, 0);
            ZhLab.Name = "ZhLab";
            ZhLab.Size = new Size(2259, 67);
            ZhLab.TabIndex = 0;
            ZhLab.Text = "这里是字幕";
            ZhLab.TextAlign = ContentAlignment.MiddleCenter;
            ZhLab.MouseDown += ControlMouseDown;
            ZhLab.MouseMove += ControlMouseMove;
            ZhLab.MouseUp += ControlMouseUp;
            // 
            // JaLab
            // 
            JaLab.BackColor = Color.Transparent;
            JaLab.Dock = DockStyle.Fill;
            JaLab.Font = new Font("Microsoft YaHei UI", 32F);
            JaLab.ForeColor = Color.White;
            JaLab.Location = new Point(0, 0);
            JaLab.Margin = new Padding(5, 0, 5, 0);
            JaLab.Name = "JaLab";
            JaLab.Size = new Size(2259, 530);
            JaLab.TabIndex = 1;
            JaLab.TextAlign = ContentAlignment.BottomCenter;
            JaLab.MouseDown += ControlMouseDown;
            JaLab.MouseMove += ControlMouseMove;
            JaLab.MouseUp += ControlMouseUp;
            // 
            // MainForm
            // 
            AutoScaleDimensions = new SizeF(19F, 41F);
            AutoScaleMode = AutoScaleMode.Font;
            BackColor = Color.Black;
            BackgroundImageLayout = ImageLayout.Stretch;
            ClientSize = new Size(2259, 597);
            Controls.Add(JaLab);
            Controls.Add(ZhLab);
            DoubleBuffered = true;
            Font = new Font("Microsoft YaHei UI", 16F);
            FormBorderStyle = FormBorderStyle.None;
            Margin = new Padding(5);
            Name = "MainForm";
            Text = "字幕";
            TopMost = true;
            TransparencyKey = Color.Black;
            Load += MainForm_Load;
            ResumeLayout(false);
        }

        #endregion
        private Label ZhLab;
        private Label JaLab;
    }
}

MainForm.cs ファイル:

using Microsoft.CognitiveServices.Speech;
using Microsoft.CognitiveServices.Speech.Translation;

namespace JapneseHelper
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }
        private void MainForm_Load(object sender, EventArgs e)
        {
            var sourceLanguage = System.Configuration.ConfigurationManager.AppSettings["sourceLanguage"];
            var targetLanguage = System.Configuration.ConfigurationManager.AppSettings["targetLanguage"];
            var apikey = System.Configuration.ConfigurationManager.AppSettings["apikey"];
            var region = System.Configuration.ConfigurationManager.AppSettings["region"];
            var config = SpeechTranslationConfig.FromSubscription(apikey, region);
            config.SpeechRecognitionLanguage = sourceLanguage;
            config.AddTargetLanguage(targetLanguage);
            var recognizer = new TranslationRecognizer(config);
            recognizer.Recognizing += (s, e) =>
            {
                this.Invoke(() =>
                {
                    ZhLab.Text = e.Result.Text;
                    foreach (var element in e.Result.Translations)
                    {
                        JaLab.Text = element.Value;
                    }
                });
            };

            recognizer.StartContinuousRecognitionAsync().ConfigureAwait(false).GetAwaiter();
        }
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Rectangle workingArea = Screen.PrimaryScreen.WorkingArea;
            var x = (workingArea.Width - this.Width) / 2 + workingArea.Left;
            var y = workingArea.Bottom - this.Height;
            this.Location = new Point(x, y);
        }

        private Point mouseOffset;
        private bool isMouseDown = false;
        private void ControlMouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                mouseOffset = new Point(-e.X, -e.Y);
                isMouseDown = true;
            }
        }
        private void ControlMouseMove(object sender, MouseEventArgs e)
        {
            if (isMouseDown)
            {
                Point mousePos = Control.MousePosition;
                mousePos.Offset(mouseOffset.X, mouseOffset.Y - this.Height / 2);
                this.Location = mousePos;
            }
        }
        private void ControlMouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                isMouseDown = false;
            }
        }
    }
}

効果画像:

画像

 ちょうど今週、営業部との会議で数回試用しましたが、全体的な意味は理解でき、現場の環境とも少し関係がありました。

(Translated by GPT)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?