ChatGPTの力で業務課題を解決したい
こんにちは、小売企業に勤めているnaripokです
今回は身近な業務課題の解決を目指し、ChatGPTの力を借りて、アプリを作ってみました。
会議の音声を録音し、テキスト化するアプリです。
ぜひ読んでいただけると嬉しいです。
作成したアプリ
╋━━
— Ka4128 (@Ka4128_1) December 9, 2023
会議記録アプリをつくってみました👨💻
━━━╋
#protoout #ChatGPT #CodePen #会議記録 pic.twitter.com/ojRQ4pbSwU
なぜ今回このアプリを作ったか
私はシステム関係の仕事をしており、
仕事柄、日々、他企業との打ち合わせや社内の会議をおこなっています。
会議の内容は新人さん達がメモとって、打合せ後には、議事録にまとめ、
参加者に共有をしてくれます。
しかし、その会議内容を正確にメモするのがとても大変です。
専門用語が飛び交う中、新人さん達はメモを取りますが、まだ理解が伴っていないため、
内容がでたらめになってしまうことが多く、後から確認をおこないます。
音声のメモを自動でとってくれるロボットがあればいいのに・・・
そんな身近な小さな課題を解決すべく、音声データをテキストとして生成してくれる
アプリの作成をしてみました。
作成手順
ChatGPTに作成したいアプリについて指示を入力し、出力されたコードを
CodePenに実装していきます。
入力したプロンプト文です。
会議での音声をテキスト変換し、議事録を作成するHTML文の生成をお願いしました。
ChatGPTが以下回答を提示してくれました。
生成されたHTMLコード
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>音声録音アプリ</title>
<style>
#startBtn, #stopBtn {
padding: 10px;
font-size: 16px;
margin: 10px;
}
</style>
</head>
<body>
<button id="startBtn">録音開始</button>
<button id="stopBtn" disabled>録音停止</button>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Recorder.jsの初期化
var audioContext = new (window.AudioContext || window.webkitAudioContext)();
var recorder;
// ユーザーのデバイスが録音をサポートしているか確認
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ audio: true })
.then(function (stream) {
// 録音ボタンのイベントリスナー
document.getElementById('startBtn').addEventListener('click', function () {
startRecording(stream);
});
// 停止ボタンのイベントリスナー
document.getElementById('stopBtn').addEventListener('click', function () {
stopRecording();
});
})
.catch(function (err) {
console.error('録音がサポートされていません: ', err);
});
}
function startRecording(stream) {
recorder = new Recorder(stream);
recorder.record();
document.getElementById('startBtn').disabled = true;
document.getElementById('stopBtn').disabled = false;
}
function stopRecording() {
recorder.stop();
recorder.exportWAV(function (blob) {
// 録音が終了した後の処理
var audioURL = URL.createObjectURL(blob);
var audioElement = new Audio(audioURL);
audioElement.controls = true;
document.body.appendChild(audioElement);
// 以下は議事録の作成などの処理を追加できます
});
recorder.clear();
document.getElementById('startBtn').disabled = false;
document.getElementById('stopBtn').disabled = true;
}
});
</script>
</body>
</html>
味気ない画面になってしまいました。
また、音声を録音するのみで再生もできず何の意味もありません。
読み取った音声をテキスト化したいです。
そこで、追加でプロンプトを入力しました。
生成されたHTMLコード
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>音声認識アプリ</title>
<style>
#startBtn, #stopBtn {
padding: 10px;
font-size: 16px;
margin: 10px;
}
</style>
</head>
<body>
<button id="startBtn">音声認識開始</button>
<button id="stopBtn" disabled>音声認識停止</button>
<div id="output"></div>
<script>
document.addEventListener('DOMContentLoaded', function () {
var recognition = new webkitSpeechRecognition(); // Google Chrome用のプレフィックスを使用
recognition.continuous = true;
recognition.lang = 'ja-JP'; // 認識言語を日本語に設定
// 認識開始ボタンのイベントリスナー
document.getElementById('startBtn').addEventListener('click', function () {
startRecognition();
});
// 認識停止ボタンのイベントリスナー
document.getElementById('stopBtn').addEventListener('click', function () {
stopRecognition();
});
// 認識結果を処理
recognition.onresult = function (event) {
var result = event.results[event.results.length - 1][0].transcript;
document.getElementById('output').textContent = result;
};
// 認識エラー時の処理
recognition.onerror = function (event) {
console.error('認識エラー:', event.error);
};
function startRecognition() {
recognition.start();
document.getElementById('startBtn').disabled = true;
document.getElementById('stopBtn').disabled = false;
}
function stopRecognition() {
recognition.stop();
document.getElementById('startBtn').disabled = false;
document.getElementById('stopBtn').disabled = true;
}
});
</script>
</body>
</html>
パソコンのマイクを使い、音声を入力してみます。
おお、見事読み取れている!少し感動です。
ただ、アプリの画面が味気ない為、ChatGPTに以下指示をしてみました。
生成されたHTMLコード
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>音声認識アプリ</title>
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #f2f2f2;
text-align: center;
margin: 0;
padding: 20px;
}
button {
padding: 10px;
font-size: 16px;
margin: 10px;
cursor: pointer;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
}
button:disabled {
background-color: #ddd;
color: #666;
cursor: not-allowed;
}
#output {
margin-top: 20px;
font-size: 18px;
}
</style>
</head>
<body>
<button id="startBtn">音声認識開始</button>
<button id="stopBtn" disabled>音声認識停止</button>
<div id="output"></div>
<script>
document.addEventListener('DOMContentLoaded', function () {
var recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.lang = 'ja-JP';
document.getElementById('startBtn').addEventListener('click', function () {
startRecognition();
});
document.getElementById('stopBtn').addEventListener('click', function () {
stopRecognition();
});
recognition.onresult = function (event) {
var result = event.results[event.results.length - 1][0].transcript;
document.getElementById('output').textContent = result;
};
recognition.onerror = function (event) {
console.error('認識エラー:', event.error);
};
function startRecognition() {
recognition.start();
document.getElementById('startBtn').disabled = true;
document.getElementById('stopBtn').disabled = false;
}
function stopRecognition() {
recognition.stop();
document.getElementById('startBtn').disabled = false;
document.getElementById('stopBtn').disabled = true;
}
});
</script>
</body>
</html>
見た目を変更したアプリ画面がこちら。
全然カッコよくない・・・。
プロンプトを追撃してみました。
生成されたHTMLコード
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>音声認識アプリ</title>
<style>
body {
font-family: 'Helvetica', 'Arial', sans-serif;
background-color: #f7f7f7;
color: #333;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
#app-container {
background-color: #3498db;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
text-align: center;
max-width: 400px;
width: 100%;
margin: auto;
}
h1 {
color: white;
}
button {
padding: 15px 20px;
font-size: 18px;
margin: 10px;
cursor: pointer;
background-color: #2ecc71;
color: white;
border: none;
border-radius: 4px;
transition: background-color 0.3s;
}
button:disabled {
background-color: #ddd;
color: #666;
cursor: not-allowed;
}
#output {
margin-top: 20px;
font-size: 24px;
background-color: white;
padding: 10px;
border-radius: 4px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
</style>
</head>
<body>
<div id="app-container">
<h1>音声認識アプリ</h1>
<button id="startBtn">音声認識開始</button>
<button id="stopBtn" disabled>音声認識停止</button>
<div id="output"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
var recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.lang = 'ja-JP';
document.getElementById('startBtn').addEventListener('click', function () {
startRecognition();
});
document.getElementById('stopBtn').addEventListener('click', function () {
stopRecognition();
});
recognition.onresult = function (event) {
var result = event.results[event.results.length - 1][0].transcript;
document.getElementById('output').textContent = result;
};
recognition.onerror = function (event) {
console.error('認識エラー:', event.error);
};
function startRecognition() {
recognition.start();
document.getElementById('startBtn').disabled = true;
document.getElementById('stopBtn').disabled = false;
}
function stopRecognition() {
recognition.stop();
document.getElementById('startBtn').disabled = false;
document.getElementById('stopBtn').disabled = true;
}
});
</script>
</body>
</html>
作成したアプリがこちら。
少し良くなりました。枠ができて色付くだけで全然見た目は変わります。
ただ、まだシンプルすぎる為、後でもっとアレンジします。
その前に一つ忘れていた機能を追加します。
生成されたHTMLコード
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>音声認識アプリ</title>
<style>
body {
font-family: 'Helvetica', 'Arial', sans-serif;
background-color: #f7f7f7;
color: #333;
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
#app-container {
background-color: #3498db;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
text-align: center;
max-width: 400px;
width: 100%;
margin: auto;
}
h1 {
color: white;
}
button {
padding: 15px 20px;
font-size: 18px;
margin: 10px;
cursor: pointer;
background-color: #2ecc71;
color: white;
border: none;
border-radius: 4px;
transition: background-color 0.3s;
}
button:disabled {
background-color: #ddd;
color: #666;
cursor: not-allowed;
}
#output {
margin-top: 20px;
font-size: 24px;
background-color: white;
padding: 10px;
border-radius: 4px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
#transcript {
margin-top: 20px;
font-size: 18px;
white-space: pre-line;
text-align: left;
}
</style>
</head>
<body>
<div id="app-container">
<h1>音声認識アプリ</h1>
<button id="startBtn">音声認識開始</button>
<button id="stopBtn" disabled>音声認識停止</button>
<div id="output"></div>
<div id="transcript"></div>
<button id="exportBtn" disabled>テキスト出力</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
var recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.lang = 'ja-JP';
var transcript = ''; // 議事録として保持する変数
document.getElementById('startBtn').addEventListener('click', function () {
startRecognition();
});
document.getElementById('stopBtn').addEventListener('click', function () {
stopRecognition();
});
document.getElementById('exportBtn').addEventListener('click', function () {
exportTranscript();
});
recognition.onresult = function (event) {
var result = event.results[event.results.length - 1][0].transcript;
document.getElementById('output').textContent = result;
transcript += result + '\n'; // 議事録に結果を追加
document.getElementById('transcript').textContent = transcript;
document.getElementById('exportBtn').disabled = false; // ボタンを有効にする
};
recognition.onerror = function (event) {
console.error('認識エラー:', event.error);
};
function startRecognition() {
recognition.start();
document.getElementById('startBtn').disabled = true;
document.getElementById('stopBtn').disabled = false;
}
function stopRecognition() {
recognition.stop();
document.getElementById('startBtn').disabled = false;
document.getElementById('stopBtn').disabled = true;
}
function exportTranscript() {
var blob = new Blob([transcript], { type: 'text/plain' });
var url = URL.createObjectURL(blob);
// ダウンロード用のリンクを作成し、クリックする
var a = document.createElement('a');
a.href = url;
a.download = '議事録.txt';
a.click();
// オブジェクトURLを開放する
URL.revokeObjectURL(url);
}
});
</script>
</body>
</html>
テキスト出力ボタンが追加されました。
音声を取り込んで、テキスト出力をしてみます。
最後に、このダサいアプリ画面に手を加えていきます。
まずは背景から変えてみます。
調べてみると、CSS枠にコードを貼り付けるだけで好きな背景を設定できるサイトが
ありました。
背景として選んだCSSコード
body {
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/41294/hero.jpg) no-repeat center center fixed;
background-size: cover;
}
// SEARCH BEGINS
.search {
width: 500px;
height: 40px;
margin: 150px auto;
background: #444;
background: rgba(0,0,0,.2);
border-radius: 3px;
border: 1px solid #fff;
input {
width: 370px;
padding: 10px 5px;
float: left;
color: #ccc;
border: 0;
background: transparent;
border-radius: 3px 0 0 3px;
&:focus {
outline: 0;
background:transparent;
}
}
button {
position: relative;
float: right;
border: 0;
padding: 0;
cursor: pointer;
height: 40px;
width: 120px;
color: #fff;
background: transparent;
border-left: 1px solid #fff;
border-radius: 0 3px 3px 0;
&:hover {
background: #fff;
color:#444;
}
&:active {
box-shadow: 0px 0px 12px 0px rgba(225, 225, 225, 1);
}
&:focus {
outline: 0;
}
}
}
// SEARCH ENDS
背景はこれで決定です。
あとは、アプリボタンの枠の色を背景に合うように変えていきます。
ChatGPTに変え方を聞いてみました。
生成されたHTMLコード
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>音声認識アプリ</title>
<style>
body {
font-family: 'Helvetica', 'Arial', sans-serif;
background-color: #fafafa; /* ページ全体の背景色 */
color: #444; /* ページのテキスト色 */
margin: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
#app-container {
background-color: #3498db; /* 大きな枠の背景色 */
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
text-align: center;
max-width: 400px;
width: 100%;
margin: auto;
}
h1 {
color: #fff; /* タイトルのテキスト色 */
}
button {
padding: 15px 20px;
font-size: 18px;
margin: 10px;
cursor: pointer;
background-color: #27ae60; /* ボタンの背景色 */
color: #fff; /* ボタンのテキスト色 */
border: none;
border-radius: 4px;
transition: background-color 0.3s;
}
button:disabled {
background-color: #ddd;
color: #666;
cursor: not-allowed;
}
#output {
margin-top: 20px;
font-size: 24px;
background-color: #fff; /* 認識結果の背景色 */
padding: 10px;
border-radius: 4px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
#transcript {
margin-top: 20px;
font-size: 18px;
white-space: pre-line;
text-align: left;
color: #333; /* 議事録のテキスト色 */
}
#exportBtn {
padding: 15px 20px;
font-size: 18px;
margin-top: 10px;
cursor: pointer;
background-color: #e74c3c; /* ボタンの背景色 */
color: #fff; /* ボタンのテキスト色 */
border: none;
border-radius: 4px;
transition: background-color 0.3s;
}
#exportBtn:disabled {
background-color: #ddd;
color: #666;
cursor: not-allowed;
}
</style>
</head>
<body>
<div id="app-container">
<h1>音声認識アプリ</h1>
<button id="startBtn">音声認識開始</button>
<button id="stopBtn" disabled>音声認識停止</button>
<div id="output"></div>
<div id="transcript"></div>
<button id="exportBtn" disabled>テキスト出力</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
var recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.lang = 'ja-JP';
var transcript = ''; // 議事録として保持する変数
document.getElementById('startBtn').addEventListener('click', function () {
startRecognition();
});
document.getElementById('stopBtn').addEventListener('click', function () {
stopRecognition();
});
document.getElementById('exportBtn').addEventListener('click', function () {
exportTranscript();
});
recognition.onresult = function (event) {
var result = event.results[event.results.length - 1][0].transcript;
document.getElementById('output').textContent = result;
transcript += result + '\n'; // 議事録に結果を追加
document.getElementById('transcript').textContent = transcript;
document.getElementById('exportBtn').disabled = false; // ボタンを有効にする
};
recognition.onerror = function (event) {
console.error('認識エラー:', event.error);
};
function startRecognition() {
recognition.start();
document.getElementById('startBtn').disabled = true;
document.getElementById('stopBtn').disabled = false;
}
function stopRecognition() {
recognition.stop();
document.getElementById('startBtn').disabled = false;
document.getElementById('stopBtn').disabled = true;
}
function exportTranscript() {
var blob = new Blob([transcript], { type: 'text/plain' });
var url = URL.createObjectURL(blob);
// ダウンロード用のリンクを作成し、クリックする
var a = document.createElement('a');
a.href = url;
a.download = '議事録.txt';
a.click();
// オブジェクトURLを開放する
URL.revokeObjectURL(url);
}
});
</script>
</body>
</html>
指示通り、各部のカラーコードを変更していきます。
カラーコードは以下サイトを参考にしました。
画面の表題もHTMLコード内で変え、出来上がった画面がこちら。
センスがないという声がどこから聞こえてきそうですが、こちらで完成です。
- 以下、実際にお試しできます
See the Pen 会議記録_ver16 by ka_can (@ka_can) on CodePen.
作ってみての感想
ChatGPTすげー!
ChatGPTがプログラムを書けるとはよく聞きますが、コードの書き方も知らずに最終的に
こんなアプリが作れるとは思っていませんでした。
正直、コードの手直しなどかなり知識が必要だと考えていました。
ただ、やはり始めから思い描いたものを作るのはかなり難しかったです。
プロンプトの書き方や、ChatGPTにできる範囲を自分がわかっていなかったことが原因だと思いますが、何度も失敗しました。
(失敗1)読み込んだ音声をテキスト化し、要約までしてくれる機能をつけようと考えていた。
ChatGTPの回答より、Google Cloud ConsoleからSpeech-to-Text APIキーを発行し、HTMLコードに埋め込もうと進めていたが、最後の段階でCodePenにAPIキーを入れるのは、他者への情報公開となり、かなり危険であるとわかった。(うまくいかず、何度もChatGPTと会話している最中に教えてくれた。)※CodePen非公開化は有料で断念
(失敗2)音声をより正確に拾えるよう実用的なアプリの作成をChatGPTに指示してしまった。
ChatGPTが出力したPythonのコードを実行できるように、Windows版Pythonをインストールし、Google Colab上で動かそうと実行したが、何度やってもうまくいかなかった。(実装するだけの知識が全く足りなかった。)
理想を実現するためには他に方法があったかもしれませんが、今回ChatGPTからは答えを見つけられませんでした。
ChatGPTへの理解と、まだまだ自分の力をわかっていなかったことが原因だと思います。
また、今回ChatGPTを使ってみてわかった事があります。
出力されたコード結果に対して、さらに機能追加の要望をすると、新たに作成されたコードでは、前回できたことができなくなっている場合がある。
(体験例)ボタンが機能しなくなった
これからChatGPTにチャレンジする方に、これらの体験談が少しでもお役に立てればうれしいです。
最後に
理想としているものが作れなかったのは、すごく悔しいです。
おそらく、今の音声言語の識別精度では会議の会話をほとんど拾えません。
マイクに向かってはっきりと話せば言語識別するレベルです。
※実際の会議でテストするタイミングが今回はとれませんでした。
悔しいので、ChatGPTの力を借りて、本当に実用的に使えるものを作っていくことに今後もチャレンジしていきたいと思います。
応援よろしくお願いします
それでは、また