TECH PLAY

株式会社RevComm

株式会社RevComm の技術ブログ

171

この記事は RevComm Advent Calendar 2022 の 3 日目の記事です。前日は持田さんの「生産性の高い定例会議を行うための準備と進め方」でした。 はじめに 体制の紹介 運営としての活動 定例会議 企画会議 オフィスアワー 執筆をしてもらうために 「あなたに」書いてほしいという旨を伝えること 執筆者をリスペクトし、讃えること 無理をさせないこと、やれる人にやってもらうこと 終わりに はじめに こんにちは小島です。普段はサーバーサイドエンジニアとして MiiTel for Zoom の開発をしています。同時に、僕はこのブログ (RevComm Tech Blog) の管理人もしています。 今回は RevComm のチーム紹介のひとつとして、テックブログを運用するチーム体制や取り組みについて書きます。 体制の紹介 まずは体制です。RevComm ではテックブログは編集部制をとっています。つまり、企画の立案・執筆者のアサイン・スケジュール管理などを担うチームがあり、全員エンジニアで構成されています。現在、チームメンバーは 4 人です。 社内ではテックブログ運営と呼んでいるので、この記事でもそう表記します。 このテックブログ運営を立ち上げている時期に、僕が「我々は何をするためにいるのか」をスライド一枚でさっと定義しました。 2022 年 1 月に書いた運営の仕事を定義したスライドの原本 簡単にいうと、読者に記事を届けるためにやれることはすべてが仕事であるという定義です。 この定義のもとで、大きく 4 つの仕事をしています。 読者に興味を持ってもらうために、記事の内容をよりよくする(ネタ出し・企画立案) 読者に信頼してもらうために、記事を定期的に公開する(執筆スケジュール管理) 読者に不信感を与えないために、記事の内容を校正する(原稿のレビュー) 読者と接点を持つために、SNS などで更新の発信をする 重要なことは、どの仕事も読者を起点にしていることです。 読者にとって意味のあることでなければ、我々の仕事ではありません 。これは当たり前ですが、重要なことです。 運営としての活動 運営は主に次の 3 つの活動をしています。 定例会議(毎週) 企画会議(月1程度) オフィスアワー(ほぼ毎週) 定例会議 弊社では、Asana というタスク管理ツールを全社で採用しています。記事の管理には、 Asana のボード(カンバン)を利用しています。 記事の進捗管理ボード このボードを見ながら、執筆やレビューの状況などを週次の定例会議で管理しています。経験上、毎週必ず実施することが、進捗管理にとって最も効率がよいと感じています。 というのも、テックブログの執筆や運営は優先度がどうしても下がりやすい業務内容だからです。僕も含めて運営メンバーは普段プロダクトの開発などをしているので、ロードマップ実現やバグ修正などと比較すると、どうしてもブログ運営の仕事は後手に回りがちです。 そこで、毎週約 30 分の定例会議の時間を設けることで、その 30 分は自分たちが運営としての仕事について考えたり、忘れていたことを思い出したりします。1 回の時間は短くてもよいですが、毎週記事の進捗状況をチェックすることが重要だと捉えています。 企画会議 定例会議とは別に月に 1 回程度、企画会議を実施しています。 定例会議では記事の進捗などの細々とした確認ごとに終始してしまうので、新しい記事や読者に僕らが伝えたいことは何か?という視点で物事を考える時間を取っています。 実施した実績はまだ少なく、会議体としてはまだ模索中です。 企画会議という名前にはしていますが、記事の企画のブレストだけをテーマにするのはよくないなと考えています。すべては読者のためであるという原則に立ち戻り、運営としてどのような取り組みをするべきかや、読者や執筆者のための取り組みについても考える時間にしています。 そこで出てきた取り組みのひとつがオフィスアワーです。 オフィスアワー 企画会議で、運営として記事の執筆者のサポート体制を作ることがいいのではないかという意見があがりました。そこで、ある運営メンバーに主導してもらい、毎週 1 時間オフィスアワーを開催することにしました。 一般的にオフィスアワーは大学でよく使われる用語で、教員が生徒からの質問などを受け付ける時間のことです。テックブログ運営では、技術記事や社内ドキュメントに関する相談を受け付ける場としてオフィスアワーを定義しています。 RevComm では、社内会議は主に Google Meet を利用しています。毎週決まった時間(現在は水曜の16:00)に Google Meet に集まり、執筆者の質問に答えたり、記事の構成の壁打ちをしたりしています。 また執筆者に限らず、ブログについてよもやまな質問や相談も受ける場としても機能しています。 執筆をしてもらうために 執筆者とのコミュニケーションは最も重要な仕事のひとつです。そして、人と人とのコミュニケーションなので正解はありません。執筆者によって、組織によってやるべきことは違うと思います。 とはいえ、ほとんどの状況で間違っていないと僕が確信しているスタンスがいくつかあります。この記事ではそのスタンスを 3 つ紹介します。 「あなたに」書いてほしいという旨を伝えること 企画を考える時、多くの場合は執筆者をセットで考えます。 「この記事をあなたに書いてほしい」と依頼するときに、なぜ「あなた」が選ばれたのかを説明できることが重要ですし、何よりそれが企画のキモだと思っているからです。 例えば「チームのオンボーディング内容を紹介する記事を書きたいです」と言うのと、「若手エンジニアから見たチームのオンボーディング体制をテーマにした記事を書きたいから、25 歳のあなたに書いてほしいです」と伝えるのとでは、執筆を依頼された人の納得感が違うでしょう。 そして記事のネタと執筆者がマッチしていることは、記事の品質に直結します。組織論を入社 1 ヶ月のメンバーが書くことはできませんし、採用活動などで多忙なマネージャーに最近得た技術的な学びを書いてもらうのもズレた記事になってしまうでしょう。こんな記事があればよさそうだというアイデアに対して、誰が一番そのアイデアをよりよく昇華してくれるかを考える、それが企画だと思います。 そして企画を深く考えられるからこそ、エンジニアがテックブログの運営をやる意義があると思っています。 執筆者をリスペクトし、讃えること 最初依頼から記事の完成まで、執筆者をリスペクトすることが大事だと考えています。 運営は依頼をする立場です。へりくだるのもまたおかしいですが、一緒に記事の作成プロジェクトを進める仲間だととらえ、プロダクト開発のチームメンバーに接するのと同じように接するのがよいと考えています。 また、公開後は執筆者を讃えます。記事の公開当日は社内の Slack で更新を通知し、みんなで讃えます。これに加えて、月に 1 度行われるエンジニアの全体会議で記事を執筆いただいた方の名前を挙げ、感謝するようにしています。 社内 Slack での更新の通知 記事の執筆は大変な仕事です。それを完遂した方には、重ねて感謝しましょう。 無理をさせないこと、やれる人にやってもらうこと 最後に、お互い無理にやろうとしないこと、やれる人にやってもらうことです。これが個人的に最も重要視していることです。 技術記事を書くのは簡単なことでしょうか?特にブログを運営するような人や日常的に記事を書いている人であれば、「記事なんて誰でも書ける」とさえ思っているかもしれません。 しかし、そんなことはありません。どんな文書も訓練しないと書けないし、適性もあるでしょう。また、普段から記事をよく書いている人でも、事業にインパクトのある仕事をしているときにブログ記事の執筆を優先することは難しいでしょう。誰でも指名すれば記事のひとつくらいは書ける、というのは暴論だと思います。 そして重要なことですが、発信の方法は文書執筆がすべてではありません。社内でアンケートを取ったところ、文書執筆は苦手でも登壇には意欲がある人や、スライド作りには苦手意識がない人もいました。要は、人には向き不向きがあるのです。文書執筆が得意ならテックブログで、人前でしゃべることが好きならイベント登壇で、ソフトウェア作りが得意なら OSS という形で発信してもらうのが一番いいと思うのです。 テックブログには採用広報メディアという性格もあります。採用のために何が伝わるといいのかと考えれば、僕らエンジニアが楽しく働いていることが伝わるのが一番だと考えています。とすると、無理にブログを書いてもらうことはむしろ逆効果になりかねません。 体制が未熟でブログ以外の発信の場をまだ用意できていませんが、2023 年はブログ以外の場を用意することを考えたいと思っています。 終わりに テックブログは立ち上げ初期からこの体制で運用し、少しずつ軌道に乗ってきました。最初こそ大変でしたが、徐々にテックブログは社内でも浸透してきて、最近では企画案を持ってきてくれる人や、執筆の立候補をしてくれる人も増えてきました。 立ち上げ期は越えましたが、ブログの性質上これからも継続していくことが何よりも重要です。今後もよりよい発信ができるように運営として改善していきます。そして社内の取り組みを楽しく発信できるメディア運営を目指していきます。 RevComm ではエンジニアを募集しています。このブログを読んで興味を持ってくれた方、参加したいと思ってくれた方もぜひ採用サイトをチェックしてみてください。 www.revcomm.co.jp
アバター
2022 年 12 月 9 日 (金) に開催される Developers CAREER Boost に RevComm のエンジニアの陶山嶺が登壇します。タイトルは「一歩踏み出す勇気が変える -コミュニティと出会って変わった私のエンジニア人生-」です。 イベント概要 公式サイトより引用 https://event.shoeisha.jp/devboost/20221209 さまざまな領域で新しいテクノロジーが登場している現在、ソフトウェア開発者を含め、人々の働き方も多様化しています。特定の技術に関するキャリアを歩む人もいれば、ライフステージの変化を迎えることで新たなキャリアを選択する人もいるなど、「エンジニアの生き方」と一口に言うこと自体難しくなってきています。 Developers CAREER Boostでは、自分の価値を最大限に発揮できる場所で、年齢やロールに縛られないキャリアを実現している先人たちの知見や、技術エキスパートがこれまで歩んできたキャリア戦略をお届けすることで、不確実性の高い今の時代を生き抜くスキルとキャリアをブーストします! ぜひこの機会に、これからのエンジニアの生きざまを考えてみませんか? 日程: 2022 年 12 月 9 日 (金) 会場: オンラインのみ 参加申し込みは こちら 主催: 株式会社翔泳社 CodeZine編集部 登壇情報 一歩踏み出す勇気が変える -コミュニティと出会って変わった私のエンジニア人生- PyCon JP への参加をきっかけにわたしのエンジニア人生は大きく広がり、いまでは瀬戸内海の小さな島から Python で仕事をしています。 そんな自分の人生を振り返ったとき、転機になったと感じているのは「PyCon JP との出会い」「好きな場所に住むための転職」「書籍の執筆」です。 どれも決断に迷いがなかったと言えば嘘になりますが、最初の一歩さえ踏み出してしまえば意外となんとかなるものです。 このセッションでは、わたしがコミュニティ活動から得た様々なものを紹介し、「自分も一歩踏み出してみよう」と思えるセッションを目指します。 日時: 2022年 12 月 9 日 (金) 15:25 ~ 15:55 (B-7) 登壇者: 陶山 嶺 リンク: https://event.shoeisha.jp/devboost/20221209/session/4123/ 最後に RevComm は電話営業や顧客応対を可視化する音声解析AI搭載型のクラウドIP電話「MiiTel(ミーテル)」を開発しています。 プロダクトの開発において Web アプリケーション、機械学習/深層学習などの領域で Python が広く使用されており、Django も採用しています。 「コミュニケーションを再発明し人が人を想う社会を創る」というミッションを達成するべく、一緒にプロダクトを開発して頂けるエンジニアを募集しています! hrmos.co
アバター
この記事は、RevComm Advent Calender 2日目の記事です。 挨拶 株式会社RevCommでバックエンドチームのマネージャーをしている持田と申します 👨 RevCommとは名前の通り、コミュニケーション ( Com munication) を再発明 ( Re in v ention) することをミッションとしている会社で、普段から相手を思い遣った交流を大事にしています。 私がPMとして定例会議の運営をしているオンライン会議ソリューションの開発プロジェクトでも、ミッションを反映して、より生産性の高い会議を開催できるように制度を整えてきたので、その知見を共有したいと思います💡 準備編 故事成語でも 事予則立 という言葉があります。全てのことは、事前によく考えて準備すればうまくいくという意味の言葉です。もちろん定例会議の前にも、準備をすることが役立ちます。 毎週行うMTGのために都度議事録用のファイルを作成するのは手間です。普段から利用している タスク管理ツールに、自分がアサインされているタスク 1 の情報を書き込むようにします。 「開発環境にリリース済み。テストケース作成中」というような具合です。 タスクに情報を集めることが重要です。 もし、あなたのプロジェクトで定例会議の為だけに資料を作成しているのであれば、極力辞めるべきです。タスクに情報を集めておくことで、アサイニーが転職したり体調を崩したりしても、タスクに関わる情報をうまく引き継ぐことができます。年末休暇明けに自分のタスクを思い出す場合にも役に立ちます。 弊社では、多くのプロジェクトで Asana を採用しています。 全員がAsanaを使うことを強制されているわけではありません。例えば、 Github Project を使っているプロジェクトも存在します。これはメンバーの話し合いで決められています。 いずれのツールも得意不得意があり、選択は会社によって異なるかと思いますが、できるだけ会社で1つのタスク管理ツールを採用することをオススメします。統一することで、プロジェクト間をまたがるタスクの依存関係が定義できたり、自動的な相互リンク、共通のマイルストーンの設定などが可能になるためです。 2 弊社でもAsanaの利用に向けて移行が活発になってきています。 また、採用するツールが決まっていても、プロジェクトとしての運用方針を決めて説明するドキュメントや、運用方針を強制する仕組みが無いと、できることが多すぎて中々メンバーに使ってもらえません。 下記のようなカスタム機能で、運用方法がわかるようにしておくと自律的な更新が期待できます。 GitHubの Issue テンプレート Asanaのタスクテンプレート、ルール あくまで私のプロジェクトの一例ですが、下記のようにAsanaテンプレートを設定することで必要なサブタスクが生成されます (もちろん、状況に応じてテンプレートを使用しないこともできます)。 こうすることで、タスクの進行状況がわかりやすく、副次的に新たにプロジェクトに参加したメンバーでも必要な作業がわかるような仕組みになっています。 進め方編 定例会議では、作業中のタスクについて困っていることが無いか、俯瞰的に見てスケジュール通りに進捗しているかが主な議題になります。 作業中のタスクについて困っていることが無いか確認する 各メンバーに準備の段階でタスクに情報を追記してもらっているので、画面共有で更新されたタスクを表示します。 Asanaには、 最終更新日 > 7日前 というタスクのフィルタがあるので、この結果 3 を画面に映し 4 、各担当者に更新内容を必要に応じて読み上げてもらいます。 この際に相談や決定事項、必要アクションが新たに言及されれば、タスクに書き込みます。誰かが書き込んでいる間、参加者には少し待ってもらってください。後で書くと言って忘れてしまうよりは、情報を残すことに少し時間をかける方が良い時間の使い方ではないでしょうか。 スケジュールの確認 スケジュールに関しては、 どれくらいのプレッシャーがあるか? 参加者は誰か? 上記によって説明量と説明の仕方が大きく変わるかと思います。 AsanaやGitHubに書き起こされたタスクは粒度が細かいため 5 、期初に定義したロードマップ 6 に対しての粒度が大きいレベルで進捗が分かるように意識しています。 リファクタリングや変数名などの話を聞いて疲れている😇ビジネスサイドのメンバーには、ここだけは集中して聞いてもらうようにします。場合によっては、こちらの話題を先に出す方がいいかもしれません。 この際、我々のプロジェクトでは期初に発表した Google スプレッドシートのガントチャートに赤黄青信号を示す色をつけるだけにしています。 まとめ 定例会議の前に、進捗をメモしておきましょう タスクや Issue (チケット) に情報を集めましょう Slackでは見失いやすいです 会議のためだけの資料は読み返すのが大変です タスク管理ツールの使い方を定義しましょう。ルールを書くだけでなく、使い方を制限するよう設定しましょう タスク管理ツールを画面に投影しましょう 参加者に応じて、情報共有の粒度を分けましょう 期初のコミットのトラッキングをしましょう GitHubを使っているなら、Issueと読み替えてください 。 ↩ Unito などのサードパーティの提供するタスク管理ツールの同期ツールを使えばAsanaとGitHub Issueの両方でタスクを管理するハードルは下がりますが、各ツールに属するユーザーのマスターデータなど連携不可能なフィールドも存在するため、やはり1つのツールを使うことが望ましいです。 ↩ 冒頭の準備編でコメントを追加していれば、フィルタ結果でタスクが表示されます。 ↩ タスク管理ツールを画面に映すことは、「毎週画面に映すので必ず更新してくださいね」というメッセージにもなります。タスク管理ツールを使っているけれども更新が少ない && 定例会議で使っていないというチームにはとても有効です。 ↩ これは会社によって実施是非が異なると思いますが、半期や四半期ごとにチームやプロジェクトの外に向かって機能の追加予定を発表することを示しています ↩ 例えば、ビジネスサイドのメンバーに「Refactor: isPositiveフラグを削除」というタスクを見せることにはあまり意味がない。 ↩
アバター
この記事は、RevComm Advent Calender 1日目の記事です。 今日から RevComm もアドベントカレンダーをはじめます。12/1~12/25の間、技術や研究、開発組織について毎日記事を投稿していきます。お楽しみに。 今年のアドベントカレンダーの初日の記事では、RevComm のリサーチディレクターの橋本がスタートアップ 企業における研究開発(Research & Development)の意義について書いていきます。 RevComm が提供するサービス まずは、RevComm はどんな企業なのか、どんなサービスを提供しているのか紹介します。私たちは、インサイドセールスやオンライン会議でのコミュニケーションを支援するSaaSサービス「MiiTel」と「MiiTel for Zoom」を提供しています。 MiiTel MiiTel はクラウド型の IP 電話サービスで、デスクトップアプリ、スマートフォンアプリ、ブラウザから電話をかけることができます。 MiiTel 特徴的なのは、 通話内容が音声データとしてクラウド上に保存される 音声認識による文字起こし コミュニケーションスキルの可視化 などができることです。電話で話した内容を本人もしくはチーム内のメンバーが簡単に情報共有できるようにすること、 電話営業を解析して可視化、定量化することで情報共有の効率化、新人教育やセルフコーチングに活用することができます。 MiiTel for Zoom MiiTel for Zoom はオンライン会議サービスZoomで行った会議に対して解析を行うサービスです。会議の録画、議事録の作成、会議の中でのトピックの抽出などができます。多くの技術は、MiiTel から転用しています。 MiiTel for Zoom なぜ研究開発をする必要があるのか? RevComm のように事業を主体としたスタートアップ企業においては、短期的な製品やサービスの成長が最重要課題であり、中長期的にしか成果が得られない研究開発(特に基礎研究)に力を入れるべきではないと考えている方も多いと思います。しかし、私はディープラーニングを主体とした機械学習およびAI技術をコアとした事業であるならば、積極的に基礎的な研究開発に力を注ぐ方が良いと考えています。その理由は3つあります。 先進技術のキャッチアップ 1つ目の理由は、新技術による破壊的イノベーションを素早く発明するために、先進的な技術の動向に常日頃からアンテナを張っている必要があるためです。新技術や新アルゴリズムは論文やテクニカルレポートとして公開されることが多いです。そのような論文からの情報収集を片手間な活動とするのではなく、きちんと日常的な業務として自然と情報が集まることが重要です。そのためには、研究者やエンジニアが基礎的な研究調査に時間を使うことは意味があります。ただし、ある特定の技術分野やタスクにのみ注力してしまわないように注意することも大事で、研究分野を横断するような幅広い視野を持って情報を得るように努力することを推奨します。なぜならば、どの分野で新技術が突如発表されるかわからないからです。 もう一つの重要なポイントは、アルゴリズムの詳細を理解し、そのアルゴリズムの本質を見極めることです。論文で発表されたばかりの技術やアルゴリズムは、まだ多くの問題を抱えています。真の革新的技術かどうかを判断するためには、基礎的な研究に対する理解と見極めるスキルを持った人を育てる必要があります。   新技術の素早いビジネス化 2つ目の理由は、新技術を素早くビジネス化して既存事業を拡大するためです。今年の大きな破壊的イノベーションの一つとして「画像生成AI」があります。年初の OpenAI の「 DALL·E 2 」に始まり、Googleの「 Imagen 」、Midjourneyの「 Midjourney 」、Stability AIの「 Stable Diffusion 」など様々なサービスやツールが発表されて注目を浴びました。特に Stable Diffusion が8月に公開された後、数週間で世界中でいろいろなサービスやビジネスが生まれており、まさに変革の年だったと思います。これらの画像生成は、2006年に発表された「 Denoising Diffusion Probabilistic Models 」がコア技術ではあるのですが、サービス化に寄与したアルゴリズムのほとんどは1年以内に発表されています。もちろん、OpenAIが9月に公開した多言語音声認識器「 Whisper 」にも注目しています。 20年ぐらい前であれば、研究結果が実用化されるのは、発表後10年20年後という感覚でした。しかし、2017年の「 Transformer 」、2018年「 BERT 」、2020年「 GPT-3 」を振り返ってみると、新技術が発表後1年以内にサービス化されるということが理解できると思います。特に、スタートアップ企業は新技術をどんどん取り込んで、より魅力的な製品やサービスをユーザに届けることが重要です。こういったスピード感を持ってビジネスを推進するためには、基礎研究も重要な状況にあると思います。   人材ネットワークの拡充 最後の理由は、人材獲得のためのネットワークの拡充のためです。スタートアップ創業期でも成長期でも、とにかく優秀な人が必要です。先の理由のとおり基礎研究はスタートアップにとっても重要なので、基礎研究ができる優秀な人材を常に採用していく必要があります。 それでは、研究ができる優秀な人材とどこで出会えるかというと、研究が活発な大学の研究室や学術会議(特に国際会議)で出会うことができます。大学教員や大学生・大学院生の視野は意外と狭く、いかにビジネスやスタートアップ界隈で有名になっている企業でも知られていないことが多いです。そんな人たちに興味を持ってもらう、一緒に仕事をしてもらうためには、彼らが注目する学会で活躍するしかありません。そのためには、研究してその成果を学会で発表するということは効果的です。そうすることで、日本中、世界中の研究者の目に止まり、ネットワークを拡大していくことができます。 RevComm が取り組む研究分野 RevComm は、人と人とのコミュニケーションを効率化するAI技術を開発するにあたって、以下のような分野の研究を進めています。 音声信号処理 音声認識 音声感情認識 話者分離・話者認識 保留音・留守番電話判定 音声合成 声質変換 自然言語処理 対話要約 トピック抽出 固有表現抽出・個人情報マスキング マルチモーダル 音声からの顔画像生成 自動応対エージェント 2022年の研究実績 RevComm では、自社での研究開発に加えて、筑波大学、京都大学、九州工業大学との共同研究を行っています。2022年の研究実績としては、国内外の学術会議に7本、国際学術ジャーナルに1本の論文を発表することができました。 情報処理学会 第84回全国大会 2022 春 会話音声から句読点付きテキストの End-to-End 認識 野崎樹文(京都大)、石塚賢吉、橋本泰一(RevComm)、河原達也(京都大) 音響学会 2022年春季研究発表会 Neutral/Emotional Speech Classification using Autoencoder and Output of Intermediate Layer in Emotion Recognizer Santoso Jennifer、Yamada Takeshi(Univ. of Tsukuba)、Ishizuka Kenkichi、Hashimoto Taiichi(RevComm)、Makino Shoji(Waseda Univ./Univ. of Tsukuba) NELE-GANの学習に用いる音声データ量および多様性の影響についての調査 加藤 集平、橋本 泰一 (RevComm) ICASSP 2022 Selective Multi-Task Learning For Speech Emotion Recognition Using Corpora Of Different Styles Heran Zhang, Masato Mimura, Tatsuya Kawahara(Kyoto Univ.), Kenkichi Ishizuka(Revcomm) INTERSPEECH 2022 End-to-end Speech-to-Punctuated-Text Recognition Jumon Nozaki, Tatsuya Kawahara(Kyoto Univ.), Kenkichi Ishizuka, Taiichi Hashimoto(Revcomm) Performance Improvement of Speech Emotion Recognition by Neutral Speech Detection Using Autoencoder and Intermediate Representation Jennifer Santoso, Takeshi Yamada(Univ. of Tsukuba), Kenkichi Ishizuka, Taiichi Hashimoto(RevComm), Shoji Makino(Waseda Univ./Univ. of Tsukuba)  APSIPA ASC 2022 Speech Emotion Recognition Based on the Reconstruction of Acoustic and Text Features in Latent Space Jennifer Santoso, Takeshi Yamada(Univ. of Tsukuba), Kenkichi Ishizuka, Taiichi Hashimoto(RevComm), Shoji Makino(Waseda Univ.//Univ. of Tsukuba)  IEEE Access Speech Emotion Recognition Based on Self-Attention Weight Correction for Acoustic and Text Features Jennifer Santoso, Takeshi Yamada(Tsukuba Univ.), Kenkichi Ishizuka, Taiichi Hashimoto(RevComm), Shoji Makino(Waseda Univ./Tsukuba Univ.)  さいごに RevComm では、音声解析、自然言語処理、画像処理の研究者や機械学習エンジニアを大募集しています。新しい技術を使ってユーザのコミュニケーションに革命を起こしませんか? Research Engineer 採用ページ: https://hrmos.co/pages/revcomm/jobs PRTIMES STORY「AIがコミュニケーションの質を可視化する。レブコムに聞く「音声DX」の未来とは?」: https://prtimes.jp/story/detail/wrVWQOieZZb
アバター
サーバーサイドエンジニアの小島孝弘です。今回は 2022 年 11 月 12 日(土)に行われた、DjangoCongress JP 2022 への登壇・参加レポートをお送りします。 manage.py 深堀り 講演ピックアップ Django 4.1 での Asynchronous 日経電子版でのDjango活用事例紹介 終わりに manage.py 深堀り 弊社からは 1 名、サーバーサイドエンジニアの松土慎太郎が登壇しました。以下、 DjangoCongress JP の公式サイト より引用します。 Django 管理コマンド manage.py を深掘り SHINTARO Matsudo manage.py は Django プロジェクトに欠かせない、様々な操作を行うためのコマンドラインユーティリティです。 本発表では、manage.py の内部実装を追いかけていき、どのようなことが行われているか見ていきます。 また、デフォルトコマンド (check, migrate, runserver, shell, testなど) の解説や、カスタムコマンドを非同期処理やバッチ処理で使用する事例を紹介します。 みなさんのハッピーDjango開発ライフの一助になれば幸いです。 docs.google.com 登壇では、manage.py の実装を追いかけることに始まり、Django 4 系で新しく登場するコマンドや機能の紹介、カスタムコマンドの弊社での利用例の紹介をしました。 登壇の様子 以下、登壇した松土からのコメントです。 今回、外部登壇を初めて経験させていただきました。 まずサポート、アドバイスしてくださった同僚たちに感謝したいです。当日も応援に来てくれて心強かったです。 登壇するからには、聞いてくれる人に一つでも新しい情報や気づきを持ち帰ってもらいたく、できるかぎり考え、調べ、準備しました。 また、RevCommでは、TechTalkという社内勉強会を毎週開催しており、事前にそこで発表したことによって、登壇に向けての課題を洗い出すことができました。その準備のおかげで、当日は良い発表ができたと思います。 しかし発表をしたこと以上に、みなさんの反応から得られたことがたくさんあったと感じています。聞いてくれた方、質問をしてくれた方、Twitterで反応してくれた方、ヒント・アドバイスを下さった方、多くの方から学ぶことができました。 協力してくださった方々に報いるために、また来年も登壇を目指してさらに良い準備をしていきたいと思います。 最後にこの場を用意してくださったスポンサー、スタッフの皆様に改めて感謝をお伝えしたいです。ありがとうございました。とても楽しかったです! 講演ピックアップ 筆者の小島が聞いたトークをいくつかピックアップしてご紹介します。 Django 4.1 での Asynchronous speakerdeck.com Junya Fukuda さんのトークで、Django 4.1 での非同期対応の内容と、なぜそのような実装になったのかの背景を解説でした。 4.1 での非同期対応は公式ドキュメントに以下のように書かれています。 Note that, at this stage, the underlying database operations remain synchronous (拙訳: この段階では、基礎のデータベース操作は同期処理のままであることに注意してください) この注意を読んで僕自身も「結局、非同期対応したの?してないの?」と混乱していました。それが今回の Fukuda さんの発表を聞いて整理されて感激しました。 日経電子版でのDjango活用事例紹介 speakerdeck.com 7 年間(!)もの Django での開発実績があるという日経新聞社さんの発表でした。 長い年月を経ているからこその依存関係管理や Lint などのツールの変遷、研修での工夫、社内での運用から得た Tips 集など、現場ならではの知見が豊富でした。 Tips 集の中には負荷を下げる工夫やアクセスが集中したときの対処など、運用課題に関するものが多く含まれていました。 特に HTTPS のコネクションを使い回すことで CPU の利用率を下げたという話題があり、複数のサービスにアクセスする MiiTel でもこの対策は使えそうだと感じました。早速、対応を検討しようと思っています。 終わりに 今回、個人的にも久しぶりのオフラインの技術イベントに参加しました。その場でトークを聞き、休憩時間や廊下での雑談も含め、とても密度の濃い時間を過ごしました。発表者の方に直接質問をしたり、感謝を伝えたりできて、ひとりの参加者としてとても嬉しかったです。 知らなかったライブラリや機能、各社での実践例や運用例などたくさん伺うことができて本当によかったです。 主催、運営スタッフ、スポンサー・会場提供をしてくださった日経新聞社の方々、そして参加者のみなさん。本当にありがとうございました。 RevComm では、今後も Python や Django のコミュニティへの発信に力を入れていきます。また、一緒に盛り上げていける仲間も募集しています。もし興味がありましたら、ぜひ以下の採用サイトをご覧ください。 www.revcomm.co.jp
アバター
TL;DR🤩 音声認識器Whisperの認識精度と認識速度について調査 認識精度 英語では論文同様の結果 日本語の認識精度はドメインに依存 baseモデルの推論がドメインにより不安定 ビームサーチの利用により、推論の頑健性が向上 largeモデルのCERはbaseモデルの半分程度 認識速度 baseモデルのRTFはGPUで0.104 largeのRTFは0.408 バッチサイズなどを最適化することで改善 こんにちは。RevCommのリサーチチームでインターンをしている中田亘です。 2022年9月21日にOpenAIからWhisperと呼ばれる音声認識器が 一般に公開 されました。今回は、Whisperの性能に関して調査を行ったので紹介します。 TL;DR🤩 Whisperとは 実験と結果 実験条件 認識精度 英語でのWER LibriSpeech test-clean test-other Earnings-21 日本語でのCER base, largeの比較 他のシステムとの比較 revcomm-test-setにおけるビームサーチ利用の効果 認識速度 モデルごとのRTF baseモデルにおけるバッチサイズによるRTFの変化 ビームサイズによるRTFの変化 まとめ Whisperとは Whisperは、OpenAIが発表した「 Robust Speech Recognition via Large-Scale Weak Supervision 」で提案された音声認識器です。従来の音声認識器は数千から数万時間の音声データで学習したものが主流でしたが、Whisperは68万時間もの音声データをWeb上から収集し、Transformerで学習しているところが大きな特徴です。また、学習の際には音声認識に限らず、翻訳、VAD(音声区間検出)、アライメントなどの様々なタスクで学習されています。これにより、様々な用途に適用可能な汎用モデルが学習できていると報告されています。今回は、Whisperの音声認識の性能に焦点を当て、調査を行いました。 実験と結果 実験では、AWS上にCPUインスタンス・GPUインスタンスを構築し、 OpenAIが提供している baseモデルおよびlargeモデルの認識精度・認識速度について調査を行いました。 実験条件 特筆しない限り、実験条件は下表の通りです。 EC2インスタンス CPU: c5.9xlarge (36CPU) 推論には32CPUを使用 GPU: g4dn.xlarge (4CPU, NVIDIA T4 16GB VRAM) 認識精度テストセット 英語 LibriSpeech test-clean, test-other (オーディオブック読み上げ音声) Earnings-21 (決算説明会の音声) 日本語 TED 講演音声 https://github.com/laboroai/TEDxJP-10K Common Voice Mozilla Common Voice ( https://commonvoice.mozilla.org/ja )の日本語音声データから27時間分の音声データを選んだもの revcomm-test-set (RevComm内製のデータ。通話音声、ビデオ会議音声) 認識速度テストセット revcomm-video (revcomm-test-setのうち、ビデオ会議音声のサブセット 日本語8.5時間) バッチサイズ 1 デコーディング手法 貪欲法 テキストの正規化 英語: Whisper公式実装で使用されている手法 日本語: 句読点除去 認識精度 Whisperの推論をGPUインスタンスで行い、その認識精度について調査しました。 英語でのWER 英語では、baseモデルおよびlargeモデルのword error rate(WER; 単語誤り率)を調査しました。 LibriSpeech test-clean test-other 図1 LibriSpeech test-clean test-otherにおけるbase, base.en, largeモデルによる推論結果のWER まず、図1にLibriSpeech test-clean, test-otherにおける結果を示します。この結果は、論文で示されている結果と一致しています。( 論文 Appendix D.1.1参照)WERの傾向としてbase > base.en > largeが確認されました。 Earnings-21 図2 Earnings21におけるbase, largeによる推論結果のWER 次にEarning-21における結果を図2に示します。Earnings-21は数十分の単一音声ファイルからなります。一方で、Whisperは30秒以下の音声で学習しているため、通常の推論は行えません。この問題に対して、論文では音声に 窓 を適用して30秒に切った後に、認識結果に応じて窓をスライドさせる手法が使用されています( 論文 3.8節参照)。Earnings-21でのWERですが、論文に示されているものより少し悪い結果となっています。原因としては、テキスト標準化手法の違いなどが考えられます。 日本語でのCER 日本語では、largeモデルおよびbaseモデル双方のcharacter error rate(CER; 文字誤り率)を調査しました。 base, largeの比較 図3 各日本語テストセットにおけるbaseモデル、largeモデルの性能 まず、各日本語テストセットにおける性能を図3に示します。こちらに関してもbaseモデルに比べlargeモデルが優れた性能を示しています。TEDとCommon Voiceに注目してみると、baseモデルのCERは低くないものの、largeモデルのCERはかなり低くなっています。一方でrevcomm-test-setに関しては、base、 largeともに非常に悪い認識精度となっています。baseモデルの認識結果を確認してみると、以下のような結果が散見されました。 おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで、おかげで これはTransformerなどの自己回帰型モデルで時折発生する、リピーティング(繰り返し)という現象です。revcomm-test-setのドメインがWhisperの学習に使用されたドメインと異なるため、出力が不安定になっていると考えられます。これに関しては、ビームサーチの利用により大幅にCERが改善することを後ほど紹介します。 論文 では、日本語のCommon Voice9においてCERが0.094、日本語のFLEURSにおいてCERが0.064と報告されていますが、我々が用いたテストセットのうち、特にrevcomm-test-setの認識精度では論文中にあるような低いCERにはなりませんでした。 他のシステムとの比較 広く一般に音声認識サービスを展開している他社の音声認識器を用いて、TEDとCommon VoiceにおいてCERの比較を行いました。図4-6 に、他社の音声認識器とbaseモデル (whisper-base) 、largeモデル (whisper-large) の比較結果を示します。 図4 TEDにおけるbaseモデル、largeモデルおよび他社の音声認識機の比較 図5 CommonVoiceにおけるbaseモデル、largeモデルおよび他社の音声認識機の比較 図6 縦軸をCommonVoice横軸をTEDのCERとした他社の音声認識機の比較 この結果をみると、whisper-baseの性能は奮わないものの、whisper-largeがTED・Common Voiceの双方において優れた性能を示しています。日本語のASRをしたい時に、whisper-largeは有力な選択肢であると言えるでしょう。 revcomm-test-setにおけるビームサーチ利用の効果 先ほど、revcomm-test-setにおいてCERが非常に悪くなる結果を紹介しました。この結果を踏まえて、デコーディング手法にビームサーチを利用することで認識精度が改善しないか検討を行いました。結果を図7に示します。 図7 ビームサーチ利用によるrevcomm-test-setにおけるCERの変化 図7の結果を見ると、baseモデルでは貪欲法 (greedy) と比較して、ビームサーチを利用することによりCERが大幅に改善していることが確認できます。推論結果を見ても、先ほどのようなリピーティングはほとんど確認されず、推論の頑健性が向上していることが確認できました。このことから、baseモデルを用いたrevcomm-test-setの推論において、ビームサーチの利用がかなり有効であると言えます。一方で、largeモデルに関しては、改善はしているもののbaseモデルのような大幅な改善は見られませんでした。 ビームサイズ=2の時のlargeモデルの出力を確認してみると、以下のようなものが確認されました。 正解文 Whisper largeモデルによる認識結果 (ビームサイズ 2) あのーまあこちらーどういう風に使うかっていうとこなんですけどもーあの実はーここあのヒートマップになってて色が濃いところっていうのはー電話がこう通じた時通電した時はーあのこう色がどんどん濃くなっていう感じ回数が多くなった こちらはどういうふうに使うかというところなんですけども、実はここヒートマップになっていて色が濃いところというのは電話が通じたとき、通電したときは色がどんどん濃くなっていく。回数が多くなる。 この例からは、「あのー」「まあ」などの言いよどみ(フィラー)が、whisper-largeの認識結果に含まれていないことが確認できます。これは、whisperの学習に用いられたデータセットにフィラーがほとんど含まれておらず、推論結果にフィラーが含まれにくくなっているためと推測されます。一方で、revcomm-test-setの正解文は、通話音声やビデオ会議の発話を聞こえたとおりに書き起こしたものであり、フィラーが多く含まれます。フィラーを書き起こしていないことが、CERのボトルネックとなっていると考えられます。 認識速度 認識速度に関しては、revcomm-test-setのサブセットであるrevcomm-videoの推論におけるreal time factor (RTF) を調査しました。RTFは以下の式で求められます。 本記事では、inferとglobalの2種類のRTFを調査しました。それぞれ定義は以下のとおりです。 infer: モデルの順伝播のみにかかった時間 global : 音声のデコード、メルスペクトログラム生成などの推論に必要な処理すべてを合計した時間 注意点: 今回の推論では、全ての音声を30秒にゼロパディングしています。これは、Whisper公式実装では、30秒以外の音声は入力できないようになっているためです。 モデルごとのRTF 図8 CPUインスタンス、GPUインスタンスにおけるbaseモデル、largeモデルの認識速度 CPUインスタンス、GPUインスタンスにおける各モデルのRTFを図8に示します。まず、GPUでの推論により大幅にRTFが改善することが分かります。特にlargeモデルでは、globalにおいてGPUインスタンスを利用することにより2.483から0.408へと改善しています。 また、GPUではinferとglobalでRTFが大きく異なることが確認されました。これは、CPUでデコードした音声をGPUに移動させる際の通信などが原因となっていると考えられます。こういった通信のオーバーヘッドは、処理を非同期化することにより改善できる可能性があります。 baseモデルにおけるバッチサイズによるRTFの変化 以上の実験ではバッチサイズを1としていましたが、GPUでのbaseモデル推論においてGPUの使用率を確認したところ40%程度であり、GPUの能力を最大限に利用できていませんでした。バッチサイズをより大きくすれば、さらに効率よく推論をできるのではと考え、バッチサイズによるRTFの変化を調査しました。結果を図9に示します。 図9 バッチサイズによるRTFの変化 結果から、バッチサイズ8程度が一番効率よく推論が行えることが確認できました。ただし、処理の非同期化などにより最適なバッチサイズは変化すると思われます。 ビームサイズによるRTFの変化 先ほどビームサーチの利用により、ドメインにより不安定なbaseモデルの推論がより頑健になることを紹介しました。一方で、ビームサーチを使用することにより処理が増えるため推論時間が長くなると考えられます。そこで、ビームサーチを使用することでどの程度処理時間が増えるかを調査しました。なお、推論はGPUインスタンスで行いました。結果を図10に示します。 図10 ビームサイズによるRTFの変化 まず、全体の傾向としてビームサイズが大きいほど、RTFが大きくなることが確認できます。また、面白い結果として、baseモデルのglobalに関してビームサーチ利用によりRTFが改善されていることが確認できます。これは、ビームサーチを使用することによってリピーティングが改善され、Whisperの出力token長が短くなったためにRTFが改善していると推測されます。 まとめ Whisperの認識精度および認識速度について調査を行い、結果を紹介しました。 認識精度に関しては、英語ではおおむね論文通りの結果が確認されました。一方で、日本語の認識精度については、特にRevComm内製のテストセットによる評価について、論文で示されているほど低いCERにはなりませんでした。Whisperの音声認識結果にはフィラーがほとんど入らないため、対話音声におけるフィラーを聞こえたとおりに書き起こしたテキストを正解とした評価では、CERが大きな値となることがあるようです。また、baseモデルの推論において、ドメインによってはビームサーチが極めて効果的であることも確認されました。 認識速度に関してはGPUの利用が非常に効果的であることが確認された一方で、GPU利用により順伝播以外の時間が増えることが確認されました。これはCPU-GPU間のデータの移動に時間がかかっていると推測されます。
アバター
2022 年 11 月12 日 (土) に開催される DjangoCongress JP 2022 に RevComm のエンジニアの松土慎太郎が登壇します。タイトルは「Django 管理コマンド manage.py を深掘り」です。 イベント概要 公式サイトより引用 https://djangocongress.jp/ DjangoCongress JPは日本で開催されるDjango Webフレームワークのカンファレンスです。 DjangoCongress JPは、Djangoでアプリケーションを開発している人、Djangoを学んでいる人などDjangoに関わる全ての人が参加できます。 参加する全ての人がDjangoについて交流し、出会い、学び、楽しみ、深い理解を得ることを目的にしています。 日程: 2022 年 11 月12 日 (土) 会場 日経カンファレンスルーム 参加申し込みは こちら 主催: 日本経済新聞社 デジタル編成ユニット 運営: django-ja 登壇情報 Django 管理コマンド manage.py を深掘り 公式サイトより引用 https://djangocongress.jp/#talk-11 manage.py は Django プロジェクトに欠かせない、様々な操作を行うためのコマンドラインユーティリティです。 本発表では、manage.py の内部実装を追いかけていき、どのようなことが行われているか見ていきます。 また、デフォルトコマンド (check, migrate, runserver, shell, testなど) の解説や、カスタムコマンドを非同期処理やバッチ処理で使用する事例を紹介します。 みなさんのハッピーDjango開発ライフの一助になれば幸いです。 日時: 2022年 11 月 12 日 (土) 17:10~17:55 (ROOM 1) 登壇者: SHINTARO Matsudo リンク: https://djangocongress.jp/#talk-11 最後に RevComm は電話営業や顧客応対を可視化する音声解析AI搭載型のクラウドIP電話「MiiTel(ミーテル)」を開発しています。 プロダクトの開発において Web アプリケーション、機械学習/深層学習などの領域で Python が広く使用されており、Django も採用しています。 「コミュニケーションを再発明し人が人を想う社会を創る」というミッションを達成するべく、一緒にプロダクトを開発して頂けるエンジニアを募集しています! hrmos.co
アバター
RevComm の小門です。 2022年10月14日(金)~15日(土) に開催された PyCon JP 2022 に参加しました。 弊社からは陶山 嶺、川添 貴之の2名が登壇、松土 慎太郎がコアスタッフとして参加しました。 今回はカンファレンスの振り返りとして登壇者らのコメントと、トークの感想をお送りします。 登壇振り返り 詳解 print(“Hello, world”) 誰もが知る print() 関数の処理を例に、C言語/OS レイヤーの仕組みを深堀していきます。 そして Python を含め「プログラミング言語がどのようにして動くか」という仕組みを知れるきっかけになるかと思います。 登壇者: Rei Suyama (rhoboro) アーカイブURL: - YouTube 資料: docs.google.com 登壇の感想 バックエンドエンジニアの陶山です。普段は PBX という音声通話に関わる機能の設計、開発を行っています。 コロナ禍になってからはPyCon JPに限らずオンライン登壇ばかりでしたので、オフラインでの登壇は久しぶりでした。 オフラインだと参加者が目の前にいるため、反応を掴みやすい点はやはり良かったですね。 私の登壇は1日目の比較的早い時間帯だったため、その後の休憩時間などに「陶山さんのトーク聞いていました」と声をかけてくださった方々がいてとても嬉しかったです。 他の方々のトークでは、内容も当然のことながらスピーカーの方々の話し方や立ち振る舞いから学べることも多かったので、それらも今後の自分の発表に生活かしていきたいと思いました。 Fast API と学ぶ WebRTC リアルタイム通信の仕組みとして昨今主流になりつつある WebRTC について概要から導入し、デモを通して簡単に動きを追いかけていく内容です。 登壇者: Takayuki Kawazoe (@zoetaka38) アーカイブURL: - YouTube 資料: docs.google.com 登壇の感想 ソフトウェアエンジニアの川添です。普段は社内業務を円滑化することで事業に寄与するためのチームでマネージャーをしています。 このような登壇は経験がなかったので、資料作りから発表の仕方まで試行錯誤の連続でした。 よく言われることですが、発表というアウトプットをするために細かいところまで調べてインプットできたので、発表に対してだけでなく技術面・知識面の向上もできて非常に良い経験でした! この記事をご覧頂いた皆様も、是非発表や登壇の機会があれば社内外を問わずチャレンジしてみて頂けるといいかと思います。 当日スタッフ バックエンドチームの松土がコアスタッフとして参加しました。 現地開催が3年ぶりということで混乱やトラブルが多かったかと思います。 裏方としてスタッフの皆さんがいたからこそイベントが成り立ちました。この場でも感謝申し上げます。 Python 3.11 is coming! 今回のイベントでは初日の基調講演をはじめ、Python 3.11 の性能改善 (高速化) や新機能に関わるトークが複数ありました。 Day2 16:00〜「 What's new in Python 3.11 and beyond 」より内容をピックアップします。 性能改善 例外処理のオーバーヘッドが10~15%から1%程度まで削減 正規表現の処理が10%程度高速化 関数呼び出しが10~20%高速化 “ float -heavy” つまり浮動小数の演算が行われていれば、50~60%程度高速化 ※ただし「Numpy をはじめとするライブラリは使用せず、標準機能の場合」と言及あり 上記のように一言で「性能改善」と言っても、実際は様々なケースで地道な改善が行われていることが分かります。 トータルとしては「多くの場合で 20~30% 程度の性能改善が期待できる」とのことです。 機能追加 Exception Groups (例外グループ) raise ExceptionGroup による「例外グループの送出」 except* による「例外グループの捕捉」 Asyncio Task Groups (非同期タスクグループ) asyncio.gather() の代替機能 例外グループ機能によってエラーハンドリングする 型関連 typing.Self 自身のクラスを表現するためのエイリアス クラス継承やファクトリーに最適 Variadic Generics (可変長ジェネリクス) tomlib (PEP 680) TOML パーサーの標準サポート 機能追加の全容、詳細は公式ドキュメント What’s New In Python 3.11 で確認できます。 新機能の追加とアップデート、特に asyncio と typing 周りは昨今着々とアップデートされてきており、今後は積極的に Python 3.11 に移行していきたいところです。 そして Python 3.11 に移行する だけ で性能改善が期待できるのはとても嬉しいですね。 そんな Python 3.11 は 10/24(月) にリリース予定 です! PEP 664 – Python 3.11 Release Schedule まとめ PyCon JP 2022 は3年ぶりにオフライン開催で行われ、私は今回が初めての現地参加でした。 参加した一番の感想は「 とにかく楽しかった! 」ということです。 多くのエンジニアが同じ場所に集まって技術を共有し合えることはもちろん、参加者や登壇者の熱量を現地で感じることができました。2日間ずっとワクワクしていました。 また RevComm は全社員がフルリモートで働いています。 今回登壇した陶山と川添は遠方からの現地参加だったため、今回初めて対面しました。 普段は直接会わないメンバーとイベントをきっかけに顔を合わせてたくさん話をすることができました。 左から小門、松土、川添、陶山 イベントを支えてくださった登壇者、スタッフの皆さん、協賛企業様に改めて感謝申し上げます。 来年もぜひ参加したいです! 最後に RevComm では Python でのアプリケーション開発に熱意のあるエンジニアを募集しています。 RevComm では自社プロダクト「MiiTel(ミーテル)」の開発において Web アプリケーション、機械学習/深層学習などの領域で Python を広く使用しています。高い安定性とスピードを両立して開発を進めるため、試行錯誤を続けるチャレンジングな環境です。 ぜひご応募をお待ちしています。 hrmos.co
アバター
2022年10月14日(金)~15日(土)に開催される PyCon JP 2022 に RevComm のエンジニアの陶山 嶺と川添 貴之が登壇します。 イベント概要 公式サイトより引用 https://2022.pycon.jp/ PyCon JP は、Python ユーザが集まり、Python や Python を使ったソフトウェアについて情報交換、交流をするためのカンファレンスです。 PyCon JP の開催を通じて、Python の使い手が一堂に集まり、Python にまつわる様々な分野の知識や情報を交換し、新たな友達やコミュニティとのつながり、仕事やビジネスチャンスを増やせる場所とすることが目標です。 日程: 2022年10月14日(金)~15日(土) 会場 TOC有明コンベンションホール 参加申し込みは こちら オンライン: YouTube Live 主催: 一般社団法人 PyCon JP Association 登壇情報 詳解 print("Hello, world") 新しい世界に飛び込むときの定番 Hello, world 。 Python に出逢い学び始めたとき print("Hello, world") を実行したひとも多いのではないでしょうか。 このトークでは、Python に慣れた今だからこそ改めて print("Hello, world") を実行し、その裏側で起きていることを深掘りしていきます。 Python の仕組みやシステムプログラミングの世界に Hello, world しましょう! 日時: 2022年10月14日(金) 13:00~13:30 登壇者: Rei Suyama リンク: https://2022.pycon.jp/timetable?id=ZJB8DS Fast API と学ぶ WebRTC 近年、様々な分野で使われるようになったWebRTCを使ってのクライアント・サーバ間のリアルタイム通信。 この技術はこれからのリアルタイム通信を利用したサービスに置いては必須の技術になりつつあります。 このトークでは、そんなWebRTCについて、FastAPIを利用してWebRTCサーバを簡易実装して、WebRTCの中身について実装とともに解説します。 日時: 2022年10月14日(金) 14:20~16:50 登壇者: Takayuki Kawazoe リンク: https://2022.pycon.jp/timetable?id=JKLGKZ 当日は FastAPI + aiortc を用いたデモを交えながら WebRTC の動作を深追いしていきます。 最後に RevComm は電話営業や顧客応対を可視化する音声解析AI搭載型のクラウドIP電話「MiiTel(ミーテル)」を開発しています。 プロダクトの開発において Web アプリケーション、機械学習/深層学習などの領域で Python が広く使用されています。 「コミュニケーションを再発明し人が人を想う社会を創る」というミッションを達成するべく、一緒にプロダクトを開発して頂けるエンジニアを募集しています! hrmos.co
アバター
今回は、チーム開発などにおいて運用しやすくなる、エンジニアのための「より綺麗なCSSの書き方」を紹介します。 !important を使わない 余分な div は書かない CSS セレクタを深くしない HTML に style を直接指定しない 自分より外のコンポーネントに margin の情報を持たせない まとめ !important を使わない 例えば、以下のようなHTMLがあったとします。 < style > p { color : red !important ; } </ style > < p > 青色のテキスト </ p > < p > 緑色のテキスト </ p > ここで要件として「文字色が赤なのをそれぞれに合った色にしたい」とします。 そこで blue 、 green というクラスで色を変更してみます。 修正は以下の通りです。 <style> p { color: red !important; } + .blue { + color: blue; + } + .green { + color: green; + } </style> - <p>青色のテキスト</p> - <p>緑色のテキスト</p> + <p class="blue">青色のテキスト</p> + <p class="green">緑色のテキスト</p> 結果は、文字色は変わらず赤色のままです。 これは p タグに対して !important が指定されていることが原因です。 まず、CSS には優先順位があり !important を指定しない場合、後者が優先して適用されます。 p タグ (要素型セレクタ) .blue または .green (クラスセレクタ) このような優先順位のことを「詳細度 (Specificity) 」と言います。 参考: 詳細度 - CSS: カスケーディングスタイルシート | MDN 詳細度は 0 以上の数値で計算され、ある要素に対して複数の style が指定される場合、数値(= 詳細度) の高い CSS 定義が優先して適用されます。 しかし !important を使用した場合、詳細度が強制的に上書きされてしまいます。 したがって上記HTMLの例では、 p { color : red !important ; } が優先され、文字色は赤色のままだったのです。 この場合、文字色を変更するには .blue や .green の各クラスにも !important を指定するしか方法はありません。 上記で紹介した MDN の参考リンクでも !important の使用は「 悪しき習慣 」とされています。 また詳細度の計算例をご紹介します。 ( Specificity value が高いほど優先順位が高い状態となります) 引用: CSS Specificity - W3Schools 今回のように、影響範囲が目に見える形であればよいですが、そうでない場合は「想定していない箇所まで修正してしまう」ことになります。 基本的に !important は使わない運用にした方が良いでしょう。 仮に運用中のコードで既に !important が使われている場合、なるべく影響範囲が小さくなるような修正にするべきです。 上記例のHTMLで新たに「テキストを太字にしたい」という要件が追加になった場合、以下の修正となるイメージです。 p { color: red !important; /* こちらに変更を加えると影響範囲が大きい font-weight: bold !important; */ } /* 新たにクラスを用意して適用 */ .text--bold { font-weight: bold !important; } < p class = "text--bold" > 太字のテキスト </ p > 余分な div は書かない 「CSS の書き方とあるのに div ?」と思われるかもしれませんが、とても大切なことです。 1番の大きな理由は、次に話す「CSS セレクタを深くしない」にもつながるのですが「余分なコードを書かずに済む」ためです。 div に限らず、その要素がなくても構成が成り立つ要素を入れると、HTML の構造が複雑になってしまい、開発者・それを解釈してレンダリングするマシンにとっても優しくないコードとなります。 「セマンティクスを意識してコードを書くことで、文書構造をシンプルに保つこと」が CSS をシンプルに保つためにも非常に重要になってきます。 参考: HTML: アクセシビリティの基礎 - ウェブ開発を学ぶ | MDN 例えばよくあるパターンとしては、h2 や p を無意味に囲むものです。 Bad: < div class = "wrapper" > < div class = "head_margin" > < h2 class = "head" > h2 </ h2 > </ div > < div class = "text_margin" > < p class = "text" > あいうえお </ p > </ div > </ div > .wrapper .head_margin .head { font-size: 16px; margin-bottom: 8px; } .wrapper .text_margin .text { font-size: 14px; } これは、下記のように簡略化することができます。 Good: < div class = "wrapper" > < h2 class = "head" > h2 </ h2 > < p class = "text" > あいうえお </ p > </ div > .wrapper .head { font-size: 16px; margin-bottom: 8px; } .wrapper .text { font-size: 14px; } 無駄な div (div に限りません) は削減していきましょう。 ※ 今回は一例として 不要な div の例を出しましたが、ブロック要素をまとめる場合など例外もあるため、適材適所で使用します。 また「A > B (A の B要素にのみ適用する)」などを使っていると、クラスセレクターを当てるときに、うまく当たらない場合があります。これは下の「余分にセレクタを指定しなくて済む」に繋がってきます。 CSS セレクタを深くしない CSS セレクタを不用意に深くしてしまうと可読性が下がり、詳細度が上がってしまうため、意図しない修正をしてしまう可能性があります。 例えば「赤」という文字だけ赤色にしたいのに、うまくいかないパターンがでてきます。 例: .block > .text { color: yellow; font-size: 12px; } .block > .wrapper > .text { color: red; font-size: 12px; } .block > .wrapper > .text > .small { font-size: 10px; } < div class = "block" > < p class = "text" > 黄色 </ p > < div class = "wrapper" > < p class = "text" >< span class = "small" > ※ </ span > 赤 </ p > </ div > </ div > このように CSS 設計を考慮しない状態でクラスを書くと、深くセレクタを指定することになります。 「文字のサイズは共通化したい」のに共通化ができなくなってしまう、ということになってしまいます。 1ページのみの LP ページなどでは特に困らなくとも、大規模な Webサービス・アプリケーションでやると、管理が大変なことになります。 例えば .block ではなく .block-2 というコンポーネント配下で同じようなことをしたいとき .block-2 > .text { color : yellow ; font-size : 12px ; } .block-2 > .wrapper > .text { color : red ; font-size : 12px ; } .block-2 > .wrapper > .text > .small { font-size : 10px ; } と、同じコードを指定しなければいけません。 同じコードを複数作らずに使いまわすことで共通化ができ、可読性・管理の向上にもつながります。 先ほどのコードを CSS セレクタを深くせずに書くと、以下のような一例になります。 < style > .block .text { font-size : 12px ; } .block .text--yellow { color : yellow ; } .block .text--red { color : red ; } .text > .small { font-size : 10px ; } </ style > < div class = "block" > < p class = "text--yellow" > 黄色 </ p > < div class = "wrapper" > < p class = "text--red" >< span class = "small" > ※ </ span > 赤 </ p > </ div > </ div > 一見すると最初のコードより量が増えたように見えますが、.block 配下の .text に font-size を一括で指定することができています。 このように「階層構造が違うだけで、スタイル自体の指定は同じコード」はコード管理のコストが減るため、できるだけ共通化した方がよいです。 その他の解決策としては「ユニークなクラス名を使用する」などがあります。 (例: .block > .text も .block > .wrapper > .text も、クラスの役割は同一のため) HTML に style を直接指定しない <div style="background: blue"> のように、直接 HTML 要素に CSS を記載しているケースがあります。 このように、HTML に直接 style 要素を記述するのは避けましょう。(インラインスタイルとも呼ばれます) インラインスタイルを使用すると外部 CSS よりも優先されるため見通しが悪くなり、コードの保守性の低下につながります。 Bad: // HTML < button style = "background: blue;" > ボタン </ button > Good: // CSS .bg-blue { background: blue; } // HTML < button class = "sample-button" > ボタン </ button > 自分より外のコンポーネントに margin の情報を持たせない このデザインを作りたいとき、あなたならどうコーディングしますか? よく下記のようなコードが書かれがちですが、実はベストプラクティスではありません。 < style > .title { margin-top : 16px ; } .title_text { margin-top : 16px ; margin-bottom : 16px ; } </ style > < div class = "wrapper" > < h2 class = "title" > title </ h2 > < p class = "title_text" > sub title </ p > </ div > このように「自分より親の要素」に対して余白を空けたいときに情報を持たせるべきではありません。(この場合は .wrapper の上余白調整のためのCSS) .title を他の要素で使いたくなったときに、その要素用に CSS を書き直さなくてはいけなくなる .title の上に何か要素を置いたときに .title で保っていた上部分の余白を、新規で置いた要素に置き換えなければいけなくなる などのデメリットが出てきます。 この場合は .title に情報を持たせるのではなく .wrapper に余白の情報を持たせるべきです。 < style > .wrapper { padding : 16px ; } .title_text { margin-top : 16px ; } </ style > < div class = "wrapper" > < h2 class = "title" > title </ h2 > < p class = "title_text" > sub title </ p > </ div > まとめ 以上、より綺麗な CSS を書くためのワンポイントアドバイスを紹介しました。 アドバイスとありますが、今回記載したものはあくまで実践で得た一例になります。 開発をする上での 一つの指標にしていただければと思います。 参考リンク: MDN による CSS のまとめ: https://developer.mozilla.org/ja/docs/Web/CSS
アバター
RevComm の木村です。 所属チームはInfrastructure(インフラチーム)です。 今回は、RevCommの全社オフサイトに関する記事の第3弾になります。 第1弾: 【レポート】年に1度の全社オフサイトミーティングを開催しました! 第2弾: RevCommインハウスデザインナーが取り組んだ「イベントデザイン」の制作裏話 オフラインでの開催予定だった会が急遽オンラインイベントとなり、第1部はZoom開催、第2部の懇親会はGatherでの開催となりました。 Gatherとは、2D RPGのような雰囲気でアバターを操作して会話や画面共有をしながらビデオチャットを行うことができるバーチャルスペースです。 本記事では、Gatherを利用した参加者 160人超 のオンラインイベントを実現する上で発生した課題と解決策に関して触れていきたいと思います。 記事の構成は以下のとおりです。 第1章 - バーチャルスペースの方法 第2章 - リハーサル時に発生した問題とその解決策 第3章 - イベントを終えてみての感想 第4章 - さらなる工夫 第1章 - バーチャルスペースの方法 本記事では、イベントの参加人数とコンテンツ内容は決まっているものとします。その段階でまず行うべきことが、会場の作成です。 Gather公式のテンプレートもいくつかあり、公式のマップエディタも存在するためスペース作成をブラウザ上で完結することも可能です。しかし、今回は条件に見合う公式テンプレートがなく、さらに公式マップエディタの自由度も少なく感じたため、 Tiled というマップエディタを利用してスペースを作成することにしました。 スペースの作成自体は本記事の主題ではないので軽く触れる程度に説明しますが、以下の5ステップを実行してGatherのスペースを作成しました。 32×32のマスでスペース全体のサイズを決定する Tiled上でGatherのタイルセットを配置して、PNG形式でエクスポートする PNGをPhotoShopで編集して、文字や矢印を配置する 出来上がった画像をGather上でインポートする Gather上でSpotlightやワープ設定、制限エリアなどを設定する 結果として、今回作成したスペースは以下の構成になりました。 幅1280px × 縦2560px(40マス × 80マス)の2ルーム構成 メインルーム側には司会者用にSpotlightを多数配置する サブルーム側には中継者用のSpotlightを少数配置する 各ルームの上段にはテーブルを配置する テーブルにはPrivate Areaを設定する ※スペース設計にもこだわりが隠れているのですが、本記事では割愛します。 第2章 - リハーサル時に発生した問題とその解決策 いよいよ作成した会場でリハーサルです。 前提として、今回のイベントでは、参加者に対して司会者が画面共有をしながら運営を行う必要がありました。 Gatherの公式ページには、100人以上の参加者がいるルームで配信を行う場合には、YouTube LiveやZoomなどの別ツールを使用することが推奨 されています。 調査をしたところ、配信者用のルームを別途用意し、会場に設置したEmbed Mediaで配信者の風景をYouTube Liveで配信するといった記事がWeb上で見つかりました。 今回も当初は見つけた記事と同様に別室からの配信を行う選択肢を検討しました。しかし、試行錯誤の結果、低遅延で画面共有を行いつつ会場の雰囲気を司会者に伝えるために配信用のルームは作成せず、メインルームの内容をサブルームに配信する方式を採用しました。 この方法であれば、各ルームの参加人数が100人を超えないように調整しながら、司会者にもライブ感を伝えることが可能です。 ※中継者の画面。参加者の反応が見えることが分かります。 懇親会のコンテンツとしては複数の企画がありましたが、その一つに ennoshita と言うツールを利用したクイズがありました。クイズの設問もその場で提示され、回答までの時間制限もある、リアルタイム性が厳しく求められるコンテンツです。 ※実際に実施されたクイズの画面。 当初検討していたYouTube Liveを利用する方法では、数秒の遅延が発生することがあらかじめ分かっていました。そこは司会者の話術でカバーしてもらう想定でしたが、実際にリハーサルを実施してみると、話術ではカバーできない問題が発生しました。 具体的には、ライブ配信を見ている人によって配信のタイムラインがずれるという問題です。司会者の知らないところで配信が遅れている状態では、クイズの進行が成り立たなくなるため致命的です。 また、GatherのEmbed Mediaの仕様も、この問題をより深くした理由です。 GatherのEmbed MediaにYouTube Liveを埋め込んだ場合には、YouTube側のコントロール機能が隠されてしまい、一時停止および再生のみ実施できる仕様になっています。そのため、ユーザ側の操作で最新のタイムラインに移動することが一切できません。 ※YouTube公式サイトにはある上記のコントロール機能が隠されてしまいます。 事前に小規模なテストをしていた際には、配信とのギャップが10秒ほどあれば、最新のライブ映像状態にスキップされる動作(※)が確認できていました。しかし、より大規模にリハーサルを行ったところ、そのスキップ動作が再現されない人がいました。先に述べたとおり、コントロール機能は隠されているため、こうなるとどうしようもありません。 ※実際には、一時停止後に再開するという操作が必要でした。 この問題が発覚したのは本番2日前のリハーサルで、今さらコンテンツの内容を変えることはできません。Gatherでの配信を諦め、Zoom配信に切り替えるべきかと全関係者で悩んでいたところに、とあるひらめきが天から舞い降りました。 ここからが本記事の本題です。 ひらめきにより実現された、公式のベストプラクティスを超えた配信方法の概要は以下のとおりです。 同一のPCから各ルームに中継用のアバターを設置(送信者、受信者) メインルームの画面を中継用のアバターで画面共有し、サブルーム内にSpotlightで共有 ルーム間の中継をYouTube Liveで行わず、同一のPCを利用する点が一番のポイントです。 全体構成を図にすると以下のようになります。 この方法のよい点をまとめると以下になります。 ルーム間の転送に要する遅延がほぼない(およそ0.1秒) 仮に人数がさらに倍になったとしても、ルームと中継者を増やすことでスケールアウトが可能 中継者は2ルームとも様子が見えているため、不測の事態に対応しやすい ※実際にサブルーム側の準備が整う前にクイズが進行しそうになったので、中継者をしていた私が司会者に声をかけ、進行を待ってもらいました。 逆に悪い点をまとめると以下になります。 メインルームからの一方向の共有となるため、メインルーム側の参加者からはサブルーム側の状況が見えない(※おそらく改善可能で、第4章で触れます) 中継担当者も一参加者としてイベントに参加する場合は、中継用とは別のPCが必要になる PCと画面がたくさんないと、全部を把握することが難しい ※当日はこんな形で参加していました。右上のディスプレイには、別入力で中継者の画面が全画面表示されています。 第3章 - イベントを終えてみての感想 Gatherを採用した決め手は、ホテルなどの会場を借りて実施する懇親会のように参加者が自由に各テーブルを移動しながら懇親できる場を用意したいという点でした。今回は、思惑通りに各テーブルでの会話が繰り広げられていました。 RevCommはフルリモートの社員が多いためオンラインの懇親会の開催頻度は多いのですが、普段はZoomやGoogle Meetを利用しています。今回の経験から、オフラインの空気感を再現することができるGatherを利用した懇親会もいいものだなと思いました。 第4章 - さらなる工夫 悪い点でも取り上げましたが、今回採用した方法はメインルームからの一方向配信です。 さらに大規模なイベントやコンテンツの内容次第では、ルーム間でのやり取りもしたくなることもあると思います。ということで、改善の余地がないか考えてみました。 一方向配信にしていたのは、音声がループすることが理由でした。逆に言うと、音声のループ問題さえどうにかできれば、ルーム間での双方向配信が可能になります。 改めてGatherの設定を行い、ループ問題が解決できないか確認してみました。その結果、理屈上は以下の構成を取ることにより双方向での配信が可能ではないかという結論に至りました。まだ実際に試してはいませんが、試された方がいれば ツイッター などで教えていただけると幸いです。 基本的な構成は同様 中継者を1名追加(便宜上Proxyとします) 中継者AのGather上で、Proxy BのUser Volumeをミュートする
アバター
この度、2022年10月5日(水)〜7日(金)に開催される DroidKaigi 2022 に SUPPORTER スポンサーとして RevComm が協賛します。 イベント概要 公式サイトより引用 https://droidkaigi.jp/2022/ DroidKaigiはエンジニアが主役のAndroidカンファレンスです。 Android技術情報の共有とコミュニケーションを目的に、2022年10月5日(水)〜7日(金)の3日間開催します。 日程: 2022年10月5日(水) ~ 7日(金) 会場 東京ドームシティ プリズムホール オンライン ( Youtube ) 主催: DroidKaigi 実行委員会 RevComm は技術コミュニティの応援、貢献に引き続き取り組んでまいります。 最後に RevComm では自社プロダクトの通話用アプリ「MiiTel Phone Mobile」を iOS、Android で開発しており、モバイルアプリエンジニアを募集しています。 hrmos.co
アバター
初めまして、RevCommインフラチーム所属の平島と申します。 インフラチームは、主に当社で用いられる全マイクロサービスの共通基盤の設計・構築・運用を担当していますが、それに加えてSite Reliability Engineering (SRE) 業務も担っています。その SRE 業務の一環として、サービスのセキュリティ強化に順次取り組んでいます。 セキュリティ対策の一つひとつは、技術的には地味なことも多いです。しかし、どこかに対策漏れがあれば、情報漏洩などの重大インシデントを引き起こしかねません。ひとたびそのような事態が引き起こされれば、多額の損害賠償や信用失墜による顧客離れなどのネガティブインパクトが非常に大きいため、セキュリティ向上はビジネスでは非常に重要なタスクです。 今回は以前に取り組んだ AWS 上のセキュリティ対策である、CloudFront を経由しないApplication Load Balancer (ALB) へのアクセスを制限する方法についてご紹介します。 前提 セキュリティ上の課題 方法 1:カスタムヘッダーを利用したリクエストの検証 方法 1 のデメリット 方法 2:AWS Managed Prefix Listを利用した Security Group によるアクセス制限 AWS Managed Prefix List とは 設定 まとめ 前提 今回想定するのは、以下のような CloudFront-ALB-Elastic Container Service (ECS) で構成されたアーキテクチャです。ユーザからのリクエストはすべて CloudFront が受け付け、CloudFront-ALB 間は HTTPS で接続するものとします。 また、CloudFront にはWeb Application Firewall (WAF) を設定しており、リクエストの中身を検査します。 セキュリティ上の課題 ALB は世界各所に設置された CloudFront のサーバーからアクセスを受け付けるために、インターネットに向けて設置する必要があります。逆に言えば、ALB の DNS 名が外部に漏れてしまった場合、CloudFront を経由せずとも、直接 ALB の DNS 名を指定してアクセスすることが可能です。 これは CloudFront で設定した WAF によるリクエストの検査をすり抜けることと同義であり、セキュリティリスクとなりえます。したがって、CloudFront 以外からの ALB へのアクセスを何かしらの方法で防ぐ必要があります。 方法 1:カスタムヘッダーを利用したリクエストの検証 AWSによって公式に紹介されている方法で、当初はこちらを採用していました。 大まかな方針は以下の通りです。 CloudFront において、到来したリクエストに対してカスタムヘッダーを付与する。カスタムヘッダーの値には、秘密の値を設定する。 ALB のリスナールールを設定して、カスタムヘッダーの値が秘密の値と一致するか検証する。一致した場合はアプリケーションの Target Group にリクエストを転送し、一致しない場合は 403 エラーをクライアントに返す。 それでは、AWS Console 上で具体的な設定方法を見ていきます。 まず、CloudFront の設定を行います。オリジンである ALB にリクエストを転送する際に付与するカスタムヘッダーは、オリジンの新規作成/編集画面で設定することが可能です。 ここでは仮に、ヘッダー名を "x-cf-secret"、値を "test1234" としておきます。 次に、ALB Listener の設定を行います。CloudFront でオリジンとして設定した ALB のListener Rule を編集します。今回は、HTTPS (443) のリスナーを編集します。 まず、Target Group へ転送する既存ルールについて、それぞれ条件を設定します。「条件の追加」から「HTTP ヘッダー」を選択し、CloudFront で設定したカスタムヘッダー名と値をそれぞれ入力します。 さらに、一番最後のルール(デフォルトルール)では、常に 403 エラーを返すよう設定します。 以上で設定は完了です。実際にオリジンに直接リクエストを飛ばすと、403 が返ってくることが確認できます。 方法 1 のデメリット カスタムヘッダーの情報が漏洩した場合、ヘッダーさえ付与していれば、CloudFront 以外からでもオリジンにアクセスできてしまいます。つまり、カスタムヘッダーは秘匿情報にあたりますが、方法 1 ではその秘匿情報が平文の状態で CloudFront、ALB Listener それぞれの設定に保存されることになります。そのため、開発者・運用担当者が容易に秘匿情報にアクセスできてしまいます。 秘匿情報へのアクセスを厳格に管理するなら、前記 2 つのリソースに対して、IAM Role などによる閲覧制限を行う必要があります。ただし、権限の設定が煩雑になる上、カスタムヘッダー以外の設定作業においても作業者が限定されてしまうなど、日常の開発・運用に支障をきたすおそれがあります。 方法 2:AWS Managed Prefix Listを利用した Security Group によるアクセス制限 2022年2月に CloudFront の Managed Prefix List が公開されたことで、方法 1 よりも簡単に目的を達成できることが判明しました。そのため、弊社では現在こちらの方法を採用しています。 AWS Managed Prefix List とは AWS Managed Prefix List(以下、Prefix List)は複数の CIDR Block を一括して登録・管理することができる機能です。Security Group の Rule を作成する際に、ソースとしてこの Prefix LIst の ID を指定することができます。こうすることで、Prefix List に登録されたすべての CIDR Block に対してRule が適用されます。 また、いくつかの Prefix List がデフォルトとして用意されています。CloudFront の Prefix List はその 1 つで、CloudFront から ALB へリクエストが転送される際は、この Prefix List に登録された CIDR の範囲に含まれる IPアドレスからリクエストが送られることになります。 ここでは、CloudFront の Prefix List をソースとした Security Group を作成し ALB にアタッチすることで、CloudFront 以外からのアクセスを防ぎます。 設定 まず、VPC > マネージドプレフィックスリストより、CloudFront の Prefix List を確認します。Prefix List 名 "com.amazonaws.global.cloudfront.origin-facing" が、今回使用する Prefix List です。 次に Security Group を作成します。Inboud Rule では HTTPS のソースに先ほど確認した Prefix List の ID を指定します。 最後に、作成した Security Group を ALB にアタッチすれば完了です。 実際に curl を使ってオリジンにアクセスしようとすると、応答がないままタイムアウトします。方法 1 と挙動は異なりますが、接続を阻止できていることに変わりありません。 まとめ 今回は、CloudFront 以外からの ALB へのアクセスを防ぐ方法を 2 つ紹介しました。 方法1(カスタムヘッダーを用いるやり方)と比べて、方法 2 (Prefix List を用いるやり方) は、 秘匿情報の管理が不要 作業が少ない(Security Group を作成してアタッチするだけ) という点でメリットが大きいです。結論として、何か特殊な事情がない限りは Prefix Listを用いる方法 2 をお勧めします。
アバター
今回は QA チームのインタビューです。 システム開発において QA (Quality Assurance; 品質保証) とは、成果物であるソフトウェアの品質を保証する業務を指します。RevComm においては、MiiTel に不具合がないか、新機能導入時に既存機能との整合性がとれているかなど、お客様に安心して MiiTel を利用いただくために様々な観点からテストをすることがメインの業務です。 RevComm のQA チームは 2022 年 8 月現在でこそ 6 人体制になりましたが、半分ほどのメンバーが 2022 年入社の方で構成されており、まさに、これからチームの基盤を強化していくフェーズになっています。 RevComm が提供している MiiTel は電話サービスであり、高い信頼性が求められます。一方で MiiTel for Zoom を 2022 年 7 月にリリースするなど、まだまだ機能の追加や発展も著しい側面もあります。お客様に MiiTel を安心して使っていただくため、品質向上のための取り組みは重要度を増すばかりです。 そこで今回は MiiTel の品質保証を担う QA チームの廣瀬さん、福田さんのおふたりにお話を伺い、これまでの QA チームの活動や工夫してきたこと、今後やっていきたいことなどについてお聞きしました *1 。 廣瀬 知里 新卒から IT 業界で開発、工程管理などに携わり、その過程で QA に関心を持つ。その後、エンジニアやカスタマーサポートの経験を経て、2020 年の 2 月に RevComm にカスタマーサポートとして参画。現在、RevComm の QA チームが属するサポートチームのリーダーを務める。 福田 華奈子 新卒からプログラマーとして主に Windows アプリの開発等に従事。経験を重ねていく過程で、運用・保守のみならずカスタマーサポートとしても経験を積み、2020年 10 月に RevComm にサポートチームのメンバーとして参画。入社後、サポート業務をする傍ら QA チーム立ち上げに携わる。 お客様の気持ちになってテストする 「開発も QA もお互いに尊重し合う」 自動化の及ばない領域 メンバーが助け合うようになれたら お知らせ 終わりに お客様の気持ちになってテストする ── QA チームの成立の経緯をまず教えてください 廣瀬: もともと RevComm ではエンジニアの方が責任をもってテストするという方針で、そこは徹底されていました。ですが、開発者だけではどうしてもお客様の利用状況をカバーしきれないことがあり、2021 年の夏頃に福田さんが入社されたのを機に、開発者とは異なる目線でのテストを本格的に始めよう、というのがチーム発足の経緯です。 ── RevComm の組織図では QA チームは開発チーム配下ではなく、カスタマーサポートチーム配下になっています。その理由はなんでしょうか 廣瀬: 成り立ちからもわかるように、元からユーザー目線といいますか、お客様の気持ちになってテストをしてみたくなった、というのが発端にあります。それはサポートという仕事をしているからできた発想だったのかなと思います。 大きな開発組織だと、開発部門のQAチームと全体の品質管理の部門とで分かれているような組織もあります。後者がユーザー目線でのテストをするチームで、わたしたちが目指しているのは後者の役割を担うことです。 ── 機能を実現できているかなどが中心となる作り手の視点でのテストというより、ユーザー目線でのテストをするチームということですか? 廣瀬: そうです。お客様は開発者が意図しない操作をすることもあるんですが、それを作り手が意識してテストすることは難しいんじゃないかなと。開発者とは違う目線、違う視点でできるテストもあるんじゃないか、その両方のテストをやることで品質面に貢献できるんじゃないかと考えています。 福田: サポートチームに上がってくる問い合わせは開発者やサポートチームも予期していなかった使い方があがってくることもあるので、その知識をテストの観点に活かせるのがいまの体制の強みかなと思っています。 「開発も QA もお互いに尊重し合う」 ── QA 業務でやりがいを感じるときはどんなときですか? 福田: 開発者が新たに実装したものが、お客様の目線からするとすごく大きな変化になってしまうなと感じることがたまにありました。これをそのままリリースするとお客様が困ってしまいますよ、ということを開発者に伝えると受け止めてもらえるんですね。そして、じゃあどうしようかという建設的な議論ができます。それが RevComm の凄いところだと思います。 これが仕様なんだよで終わらないで、一回考えようと議論をする場面が結構多いので、気づいたことをお伝えできると、とてもよかったなと思います。 ── 議論をして実際に改善につなげられているのは素晴らしいことですね。開発チームとのコミュニケーションで何か工夫していることはありますか? 廣瀬: 福田さんに開発チームのテストや品質改善に関わるチームのミーティングに毎週参加してもらって、開発チームの取り組みをキャッチアップをしています。毎週参加することでお互いの立場を理解しようと努めているとか、小さいことの積み重ねから信頼が生まれていったのかなと思います。 あとやっぱり、開発とテストはぶつかることも正直あると思うんです。でも、率直に意見を交わしてもあまりぶつからないでできているのは、お互い頼っているし、尊重することができているからだと思っていて。それは QA とか関係なく、全社的に相手の立場に立ったコミュニケーションをお互い意識できているからなのかなと思います。 自動化の及ばない領域 ── 開発チームと連携して Autify の導入を進めていますが、自動化についてはどんな恩恵を感じていますか? 福田: 単純に、リリース後の手動確認の負荷が軽減されましたね。問い合わせベースの不具合修正をリリースしてもらうとき、今まではその周辺で問題が起きてないかとか不安になることもあったんですが、今はテストが実行されて Slack でテストの成功通知を見るとやっぱり安心感が違います *2 。 廣瀬: 自動化自体もそうなんですが、導入を機会に仕様や機能を体系的に整理するきっかけになったと思うんですよね。 サポートチームがこれまで内々で作ってきたテストケースや仕様の整理が開発チームの方に活用いただけたり、逆に開発チームの方がつくったテストケースで新たな観点を知ったり。製品に対する理解をチームをまたいで深めるような相乗効果があったように感じてます。 ── ツールの手が及ばない、人の手がどうしても必要な部分ってありますか? 廣瀬: 電話という特性上、お客様の環境や外部要因ということもあるので、そういう部分はどうしてもカバーしきれないところはありますね。 たとえばモバイルアプリの場合、アプリの問題なのか、OS のバージョン差異起因なのか、はたまた端末固有の事象なのかということもあって。切り分けも難しいし、再現が難しいことがあるとどうしても時間がかかりますね。 多くの Web アプリケーションだと、お客様からご報告いただいた事象はだいたいこちらでも再現できるんですけど、電話アプリだと必ずしも再現しきれなかったりするのでそれが難しいなと思いますね。 メンバーが助け合うようになれたら ── これからやりたいことを教えてください 廣瀬: メンバーが増えたので、やっと今までよりも時間を割けるようになってきたので、もっと QA の観点を醸成していきたいですね。 それから QA チームの体制作りに本腰を入れていきたいです。いったんプロダクトそれぞれに対してメンバーをメイン担当にアサインしてという形で体制作りをしていきます。 一方でユーザー目線のテストという観点だと、自分の担当プロダクトしかわからない、だと難しいと思っています。幅広く知識を得るためにも、それぞれのメンバーが助け合って動けるようになれたらいいなと思っています。 ── チームとしてより成果をあげるための体制作りをこれから時間をかけてやっていくということですね。これからもご協力よろしくお願いします。今回はありがとうございました! お知らせ RevComm の QA チームの大野泰代が、2022 年 10 月 1 日(土)に行われる 「XP 祭り 2022 @ Online 」にて登壇します。 xpjug.com XP 祭りはソフトウェア開発の現場をよりよくするためにできることを発表する場です。大野はRevComm への転職を踏まえて、QA エンジニアが自分のスキルや働き方にマッチした転職方法を紹介する予定です。 QA チームメンバーの話を直接聞ける場になります。お時間ありましたらぜひご参加ください。 終わりに MiiTel はこれまでになかった価値を届けるプロダクトであると同時に、電話というお客様の業務のインフラとなるプロダクトでもあります。日々お客様が安心して使えるよう、品質保証への取り組みをさらに強化していきます。 この記事を読んで MiiTel の開発や品質保証に興味をもっていただけた方は、ぜひ当社の採用サイトをご覧ください。 www.revcomm.co.jp 企画・聞き手・文責 小島孝弘 RevComm Tech / Backend チーム 聞き手・編集 小門 照太 RevComm Tech / Infrastructure チーム *1 : インタビューはオンラインで実施しました。 *2 : より詳しくは Autify 社からのインタビュー もぜひご覧ください:
アバター
モバイルエンジニアの長尾です。 最近は暑くてすっかり外に出なくなってメタボ体型になってしまったので、定期的に運動する方法としてジムに通うようになりました。やっぱり運動はいいっすね。 はじめに バックグラウンドでの着信時の動作 フォアグラウンド状態での動作をバックグラウンド状態でも続けたい時の動作 まとめ 最後に はじめに みなさんは、iOSアプリは、ユーザーには見えていないけれどもアプリが動いている状態があることをご存じですか? iOS アプリはバックグラウンド状態でのアプリの動作は厳しく制限されていて、ユーザーに見えない状態において、アプリはほとんど動かせません。しかし、いくつかのケースにおいては、バックグラウンド状態でもアプリを動作させることができます。 例えば、ミュージックプレイヤーのようなアプリは、アプリがユーザーから見えていなくとも、音楽を流し続けることができています。これはアプリがバックグラウンド状態になっていても、動作し続けているからこそ実現できています。 弊社で提供している MiiTel Phone Mobile は、電話アプリです。 電話という機能は、iPhone がロックされている状態でも、着信できる必要があります。この機能を実現するために、バックグラウンド状態でも動作するように設計しています。 本稿では、MiiTel Phone Mobile において遭遇したバックグラウンドでのアプリの動作ケースにおいて利用した API を2つご紹介し、それぞれの API における実装上の注意点をまとめています。 バックグラウンドでの着信時の動作 電話アプリの特徴として、電話がかかってきた際に、アプリを使用していなくても、アプリを起動させる必要がある点が挙げられます。ここで言う「アプリを起動する」とは、アプリが前面に立ち上がることだけを指しているのではなく、アプリのプロセスが動き始める、という意味も含みます。電話がかかってきた際は、少なくともサーバーと通信ができる程度にはアプリが動作する必要があります。 このようなケースにおいては、Voice-over-IP (VoIP) push notifications を用います。 VoIP push notifications を使用して、VoIP プッシュ通知を受信することでアプリを起動することができます。 ただし、VoIP プッシュ通知を受信する際は、所定の手順を実行しないと、OSがアプリを強制終了します。 もし所定の手順を実行しないようなアプリであれば、VoIP push notifications でアプリを起動させることができなくなることもあります。 ここでいう所定の手順とは以下の通りです。 pushRegistry() メソッドの中で、 reportNewIncomingCall() をコールすること reportNewIncomingCall() の completion() クロージャ内で pushRegistry() メソッドの completion() をコールすること WWDCでもかなり強い口調で言及されている *1 *2 ので、OSによって強制終了させられないようなコードにしておく必要があります。 pushRegistry() メソッドは、PKPushRegistryDelegate に定義されているデリゲートメソッドで、VoIP プッシュ通知を受信した際にOSからコールされるメソッドです。 reportNewIncomingCall() メソッドは、CXProviderクラスに定義されたメソッドで、画面に着信画面を表示するためのメソッドです。 reportNewIncomingCall() メソッドをコールすること自体に制約はありません。 所定の手順を満たそうとすると、VoIP プッシュ通知を受信した際に必ず着信画面が表示されることになります。 コード例を例示しておくので、参考にしてください。(WWDC のセッションで表示されていたコード *3 を参考にしています) let provider = CXProvider(configuration : providerConfiguration ) func pushRegistry (_ registry : PKPushRegistry , didReceiveIncomingPushWith payload : PKPushPayload , for type : PKPushType , completion : @escaping () -> Void ) { if type != .voIP { return } guard let handle = payload.dictionaryPayload[“handle”] as? String else { return } let callUpdate = CXCallUpdate() callUpdate.remoteHandler = CXHandle(type : .phoneNumber, value : handle ) let callUUID = UUID()    // 1. pushRegistry(_:,didReceiveIncomingPushWith:,for:,completion:)メソッド内で、reportNewIncomingCallをコール provider.reportNewIncomingCall(with : callUUID , update : callUpdate ) { _ in // 2. reportNewIncomingCall(with:update:completion:)のクロージャ内でpushRegistry(_:,didReceiveIncomingPushWith:,for:,completion:)メソッドのcompletionをコール completion() } establishConnection( for : callUUID ) } もし、先ほどの所定の手順を実行しなければ、以下のようなエラー文がコンソールに出力されます。ログに現れている通り、アプリは強制終了させられます。 2022-08-25 14:36:30.016132+0900 AppName[4899:1149881] Apps receving VoIP pushes must post an incoming call (via CallKit or IncomingCallNotifications) in the same run loop as pushRegistry:didReceiveIncomingPushWithPayload:forType:[withCompletionHandler:] without delay. 2022-08-25 14:36:30.016292+0900 AppName[4899:1149881] *** Assertion failure in -[PKPushRegistry _terminateAppIfThereAreUnhandledVoIPPushes], /Library/Caches/com.apple.xbs/Sources/PushKit/PushKit-37/PKPushRegistry.m:343 2022-08-25 14:36:30.017563+0900 AppName[4899:1149881] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Killing app because it never posted an incoming call to the system after receiving a PushKit VoIP push callback.' *** First throw call stack: (0x1b0851654 0x1b0573bcc 0x1b07546ec 0x1b0b9a16c 0x1c4a47ab8 0x107d2b730 0x107d3a488 0x1c4a46a70 0x107d2a338 0x107d2b730 0x107d39710 0x1b07cf6bc 0x1b07ca590 0x1b07c9ba8 0x1ba940344 0x1b49053e4 0x102def5b4 0x1b06518f0) 中でも、2. の手順は、見落としがちなので注意が必要です。 また、2. の手順は pushRegistry() メソッド内でなるべく早く実行することをお勧めします。サーバーとの通信の確立等やらないといけないことも色々あると思いますが、b)の手順を行っておいてからでも遅くはないはずです。 フォアグラウンド状態での動作をバックグラウンド状態でも続けたい時の動作 アプリを使用中に、通信が長くなってしまうと、ユーザーが痺れを切らして、スマホをロックしてしまうケースはよくあることだと思います。こういったユースケースでは、フォアグラウンド状態の時にはじまった通信がバックグラウンド状態になっても継続し、通信が完了するまで動作し続けることが望ましいです。 そのようなケースで使うのが、Background Task Completion です。 Background Task Completion の使い方は、以下の通りです。 UIApplication.beginBackgroundTask をコールして、OSに対して Background Task Completion が開始されたことを通知する タスクが完了した時点で、UIApplication.endbackgroundTask をコールし、Background Task Completion を完了させても良いことをOSに対して通知する 必要であれば、定められた時間内に、タスクが完了できなかった場合、エラー通知などタスクが完了できなかった時の後始末を行うコードを、beginBackgroundTask メソッドの expirationHandler 引数へ定義しておく 使用例を示します。こちらも WWDC のセッションで表示されていたコード *4 を参考にしています func send (_ message : Message ) { let sendOperation = SendOperation(message : message ) var identifier : UIBackgroundTaskIdentifier! // ここからバックグラウンドになっても継続したい処理が開始されることをOSへ通知する identifier = UIApplication.shared.beginBackgroundTask(withName : “sendOperationTask”,expirationHandler : { sendOperation.cancel() postUserNotification(“Message not sent, please resend”) // バックグラウンドでの動作が継続できる時間を過ぎてしまった時に呼ばれる }) sendOperation.completionBlock = { // バックグラウンドでも継続したい処理が完了したことをOSに通知する UIApplication.shared.endBackgroundTask(identifier) } operationQueue.addOperation(sendOperation) } ここで大事なことは、beginBackgroundTask をコールした後、必ず endBackgroundTask をコールすることが必要ということです。 beginBackgroundTask をコールしたにもかかわらず、endBackgroundTask をコールしないとどうなるでしょう? 答えは簡単で、OS によってアプリが Terminated されます。 ちゃんと endBackgroundTask をコールできていないと、以下のようなメッセージが出るので、気をつけましょう。 [BackgroundTask] Background Task 145 ("sendOperationTask"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this. まとめ 本稿においては、バックグラウンドでの動作ケースにおいて利用したAPIを2つ挙げ、それぞれのAPIにおける実装上の注意点をご紹介させていただきました。本稿では取り上げませんでしたが、バックグラウンド中に少しだけアプリを起動して、情報をリフレッシュしておくと言った使い方のできるAPIも用意されています。興味がある方は「Background Task App Refresh *5 」で調べてみてください。 本稿がご参考になれば幸いです。 最後に RevComm は 9月10日(土)〜12日(月) に開催される iOSDC Japan 2022 *6 にシルバースポンサーとして協賛します。 RevComm では自社プロダクトの通話用アプリ「MiiTel Phone Mobile」を開発しており、モバイルアプリエンジニアを募集しています。 hrmos.co iOSDC トークンはこちら! #RevCommでMiiTelを一緒に作りませんか *1 : Advances in App Background Execution - WWDC19 - Videos - Apple Developer 9:40から *2 : And new this year, it's very important that you know that you must report incoming calls with CallKit in the didReceiveIncomingPush callback or your app will be terminated. And, if you repeatedly do this, or if you repeatedly fail not to report an incoming call, the system may stop launching your app for VoIP pushes altogether. *3 : Advances in App Background Execution - WWDC19 - Videos - Apple Developer 10:04から *4 : Advances in App Background Execution - WWDC19 - Videos - Apple Developer 7:34から *5 : https://developer.apple.com/documentation/backgroundtasks/bgapprefreshtask *6 : https://iosdc.jp/2022/
アバター
RevComm では自社プロダクト「MiiTel」におけるお客様向けの通話用アプリを iOS、Android で開発し「MiiTel Phone Mobile」としてご提供しています。 この度、2022年9月10日(土)〜12日(月)に開催される iOSDC Japan 2022 にシルバースポンサーとして協賛します。 イベント概要 公式サイトより引用 https://iosdc.jp/2022/ iOSDC Japan 2022 はiOS関連技術をコアのテーマとしたソフトウェア技術者のためのカンファレンスです。今年はリアル会場とオンライン配信のハイブリッド開催を予定しています。 日本中、世界中から公募した知的好奇心を刺激するトークの他にも、パンフレットに掲載された技術記事、参加者であれば誰でも作れる即興のトーク・アンカンファレンスなど、初心者から上級者まで楽しめるコンテンツがみなさんを待っています。 日程: 2022年9月10日(土)〜12日(月) 会場: 早稲田大学 理工学部西早稲田キャンパス オンライン(ニコニコ生放送) 主催: iOSDC Japan 2022 実行委員会 参加申し込みはこちら https://www.eventbrite.com/e/iosdc-japan-2022-tickets-347187606477 今回は弊社メンバーの登壇、スポンサートークはありませんがコアスタッフとして1名が参加予定です。 RevComm には #電話営業をAIで可視化するMiiTel(ミーテル) を開発する多くのエンジニアがいます。 今後も技術コミュニティの応援、貢献を継続してまいります。 最後に、下記はコアスタッフとして参加予定の長尾が執筆した iOS アプリ開発に関する記事です。 ぜひ合わせてご覧ください(iOSDC トークンもあります!)。 tech.revcomm.co.jp
アバター
RevCommで音声処理の研究開発を担当している加藤集平です。皆さんは 電話の通話相手が屋外やカフェなどの雑音環境下にいるために、相手の声が聞こえづらくて苦労した経験はありませんか? 本記事では、 物理的な音量はそのままに 雑音環境下の聞こえ(音声了解度)を改善するモデルであるNELE-GANを用いた、通話相手が雑音環境下にいても聞き取りやすい電話の実現に向けた実験を紹介します。 弊社のサービスであるMiiTel(ミーテル)の大量の通話音声を用いてモデルを学習することで、ベースラインよりも大幅に性能を改善することに成功しました 。 ※本記事の内容は、筆者らが日本音響学会2022年春季研究発表会で発表した内容(加藤 & 橋本, 2022)に基づいています。 加藤集平(かとう しゅうへい) シニアリサーチエンジニア。RevCommには2019年にジョインし、音声処理を中心とした研究開発を担当。ADHDと付き合いつつ業務に取り組む2児の父。 個人ウェブサイト X → 過去記事一覧 要約 背景 本手法で強調した音声の例 強調前 強調後 手法 音声了解度を表す客観指標 音声品質を表す客観指標 実験 音声データおよび雑音データ モデルの学習条件および実験条件 実験結果 モデルの学習に用いる音声データの量および多様性の変化に伴う客観評価値の変化 モデルの学習に用いる雑音の多様性の変化に伴う客観評価値の変化 考察 汎化性能 音声データの量および多様性を変化させたときの音声了解度や音声品質の変化 雑音の多様性を変化させたときの音声了解度や音声品質の変化 結論 発表文献 参考文献 要約 NELE-GANを、 非常に大量のMiiTel通話音声 および様々な雑音の組合せで学習しました(学習データ量はNELE-GANの論文の実験の最大 33倍 )。 上記のデータを用いて学習した結果、 音声了解度を同程度に保つかさらに向上させた上で、音声品質を大幅に向上させることに成功しました 。 背景 雑音の大きい環境下では、同じ音声でも雑音の小さい環境下にくらべて聞き取りが難しくなります。 音声了解度 (speech intelligibility) は音声により伝えられた単語や文章が相手にどれだけ正確に伝わるかを表す尺度で、雑音環境下ではこの音声了解度が下がることが知られています。 音声了解度が下がる仕組みは未だ解明されていません。一方で、音声の周波数特性などを変化させることで音声了解度が向上することがあることが知られています。実は私たち人間は雑音環境下で無意識のうちにこれを行っており、この現象はロンバード効果 (Lombard effect) (Lombard, 1911) と呼ばれています *1 。 雑音環境下での音声了解度(つまり音声の聞き手が雑音環境下にある場合の音声了解度)を向上させるように音声を変換する(音声強調を行う)ことは、near-end listening enhancement (NELE) と呼ばれています *2 。本記事では2021年に提案されたばかりのNELE-GAN (Li & Yamagishi, 2021) を用いた実験を行います。この手法は、複数の音声了解度の客観評価値を向上させるような変換 *3 を、敵対的学習ネットワーク (generative adversarial network; GAN) によって学習します。 Li & Yamagishi (2021) では、学習データに男女各1名の英語読み上げ音声(各600文、合計1,200文)を用いています。本記事では、モデルを電話音声により適応させると同時に汎化性能 *4 をより高めるため、大量のMiiTelの通話音声を用いてモデルを学習し、その性能をベースライン(Li & Yamagishi (2021) の著者らが公開しているモデルと同等のモデル)と比較します。 本手法で強調した音声の例 強調前 強調後 ランダムな数字を読み上げている音声に、雑音を付加したものです。強調前と強調後でSNR *5 は同じにしてありますが、強調後の音声のほうがより聞き取りやすくなっていることが分かります。 手法 NELE-GANの詳細についてはLi & Yamagishi (2021) に譲りますが、モデルの構造は図1および図2のようになっています。 図1 識別器の構造 図2 生成器の構造 NELE-GANは、クリーンな音声(背景雑音をほとんど含まない音声)および雑音を入力とし、識別器からは客観指標の推定値が出力され、生成器からは音声の周波数特性を変化させるフィルタが生成されます。 識別器の学習においては、 Q 関数(複数の客観評価値を算出する関数)の出力である客観指標の真の値と、識別器が出力する客観指標の推定値の平均二乗誤差損失 (mean squared error loss; MSE loss) を最小化するように学習が行われます。一方、生成器の学習においては、客観指標の取りうる最大値と、識別器が出力する客観指標の推定値のMSE lossを最小化するように学習が行われます(このとき、識別器の重みは固定します)。これらを交互に繰り返すことで、客観評価値を最大化するようなフィルタを学習することができます。 Q 関数では、音声了解度を表す3つの客観指標に加えて、音声品質を担保するための2つの客観指標が用いられます。 音声了解度を表す客観指標 Speech intelligibility in bits (SIIB) (Kuyk et al., 2018) Hearing-aid speech perception index (HASPI) (Kates & Arehart, 2014) Extended short-time objective intelligibility (ESTOI) (Jensen & Taal, 2016) 音声品質を表す客観指標 Perceptual evaluation of speech quality (PESQ) (Rix et al., 2001) Virtual speech quality objective listener (ViSQOL) (Hines et al., 2015) 実験 音声データおよび雑音データ 音声データには、 弊社の業務において MiiTelを通じて行われた通話音声から、 弊社から発信した通話を着信した側 のチャンネルの音声区間のみを抜き出して使用しました。着信側の話者がそれほど重複しているとは考えづらいので、話者数は通話件数とほぼ等しいと見なせます。なお、音声は厳密な意味でのクリーンな音声ではありませんが、この実験のためにできる限りクリーンな音声を選別しました。 音声データについては、モデルの学習・検証のために、 S : 音声区間数2,269(通話件数466件、4.2時間)、 M : 音声区間数9,004(通話件数2,089件、16.7時間)、 L : 音声区間数34,962(通話件数7,322件、66.7時間)の3つのデータセットを用意しました。ただし、音声区間数のより多いデータセットは、より少ないデータセットを包含しています。モデルの評価のためには、学習・検証のために使用していない音声区間数116(通話件数18件、0.56時間)のデータセットを用意しました。 雑音データには、Li & Yamagishi (2021) と同じく、The Microsoft Scalable Noisy Speech Dataset (MS-SNSD) (Reddy, 2019) を使用しました。モデルの学習・検証のために、​​ a : 音声系の雑音3種類 (airport, babble, neighbor speaking)、 b : セット a (音声系の雑音3種類)+雑踏系の雑音2種類 (traffic, station) の2つのセットを用意し,それぞれ SNR = −10 dB, −5 dB, 0 dB となるように雑音を音声に重畳しました。モデルの評価のためには、 closed : 学習・検証セット a と同一種類の雑音(音声系の雑音3種類、ただし異なるサンプルです)、 acoust : 学習・検証セット a に含まれるものとは異なる音声系の雑音2種類 (bus, cafe)、 crowd : 学習・検証セット b に含まれるものとは異なる雑踏系の雑音2種類 (field, metro)、 office : オフィス系の雑音3種類 (air conditioner, copy machine, typing) の4つのデータセットを用意し、それぞれ SNR = −12 dB, −9 dB, −6 dB, −3 dB, 0 dB, +3 dB となるように雑音を音声に重畳しました。 結果として、モデルの学習・検証には S a – L b の6つのデータセット、評価には4つのデータセットを用いました(表1、2)。 S a がベースライン(Li & Yamagishi (2021) の著者らが公開しているモデル)に最も近いモデルになります。なお、学習・検証に用いた S a – L b の6つのデータセットについては、無作為に選んだ320サンプルを検証に、残りのサンプルを学習に用いました *6 。 表1 学習・検証データセットの詳細 データセット 音声データセット 雑音データセット SNR サンプル数 時間長 [h] Li & Yamagishi (2021) 1,320サンプル(時間長不明) (4種類) (3種類) 15,840 (不明) S a S (4.2時間) a (3種類) -10 dB, -5 dB, 0 dB(3種類) 20,421 37.5 S b b (5種類) 34,035 62.5 M a M (16.7時間) a 81,036 150 M b b 135,060 250 L a L (66.7時間) a 314,658 600 L b b 524,430 1,000 表2 評価セットの詳細 データセット 音声データセット 雑音データセット SNR サンプル数 時間長 [h] T closed (0.56時間) closed (3種類) -12 dB, -9 dB, -6 dB, -3 dB, 0 dB, +3 dB(6種類) 2,088 10 T acoust acoust (2種類) 1,392 6.7 T crowd crowd (2種類) 1,392 6.7 T office office (3種類) 2,088 10 モデルの学習条件および実験条件 音声および雑音の標本化周波数は8 kHz *7 とし、ミニバッチの大きさは32としました。さらに、学習の安定化と高速化のために、1エポック目はSIIB, ESTOI, PESQの3つの指標のみを用いて学習を行い、2エポック目以降は5つ全ての指標を用いて学習を行う方法を取りました。そして、3エポック目以降の学習では、当該エポックの学習を終えた時点での検証セットに対する客観評価値が、前エポック終了時のものよりも小さくなるか上昇率が1 %以下になった時点で学習を打ち切り、客観評価値の平均が最も大きなモデルを評価に使用しました。 モデルの評価においては、評価セットの各サンプルに対する客観評価値を平均したものを、当該セットに対する客観評価値としました。 実験結果 実験結果を図3に示します。 どの評価セット ( T closed , T acoust , T crowd , T office ) においても、強調後の音声 ( S a – L b ) は強調前の音声 (unmodified) に対して、音声了解度を表す客観指標 (SIIB, HASPI, ESTOI) の値は上昇傾向にあり,音声品質を表す客観指標 (PESQ, ViSQOL) の値は低下していることが分かります。 図3 各条件および評価セットの組合せに対する客観評価値 評価セット間の客観評価値の相関を見てみます(表3–5)。音声了解度を表す客観指標 (SIIB, HASPI, ESTOI)、音声品質を表す客観指標 (PESQ, ViSQOL) ごとに見れば、評価セット間の客観評価値の相関係数はおおむね0.9以上と、非常に強い相関があることが分かります。 表3 全ての客観評価値についての評価セット間の相関係数 T acoust T crowd T office T closed 0.569 0.511 0.946 T acoust - 0.994 0.769 T crowd - - 0.720 表4 音声了解度に関する客観評価値についての評価セット間の相関係数 T acoust T crowd T office T closed 0.929 0.891 0.969 T acoust - 0.994 0.977 T crowd - - 0.959 表5 音声品質に関する客観評価値についての評価セット間の相関係数 T acoust T crowd T office T closed 0.931 0.932 0.968 T acoust - 0.997 0.978 T crowd - - 0.970 モデルの学習に用いる音声データの量および多様性の変化に伴う客観評価値の変化 モデルの学習に用いる音声データの量および多様性を変化させると、客観評価値はどのように変化するのでしょうか?これを観察するために、各評価セットに対する結果を ( S a , M a , L a ) または ( S b , M b , L b ) の組合せで比較しました(図4、図5)。音声了解度を表す客観指標のうちSIIBおよびHASPIについては、 S a / S b から M a / M b へと音声データの量および多様性を大きくすると値が若干低下しましたが、 L a / L b へとさらに大きくすると値は同程度まで回復しました。ESTOIについては、音声データの量および多様性を大きくするにしたがって、単調に値が上昇しました。一方、音声品質を表す客観指標 (PESQ, ViSQOL) については、 S a / S b から M a / M b へと音声データの量および多様性を大きくすると値が上昇し、 L a / L b へとさらに大きくすると値は若干低下するか同程度となりました。 図4 各条件における ( S a , M a , L a ) の組合せに対する客観評価値 図5 各条件における ( S b , M b , L b ) の組合せに対する客観評価値 モデルの学習に用いる雑音の多様性の変化に伴う客観評価値の変化 モデルの学習に用いる雑音の多様性を変化させたときの客観評価値の変化についてはどうでしょうか?これを観察するために、各評価セットに対する結果を ( S a , S b ),( M a , M b )、または ( L a , L b ) の組合せで比較しました(図6–8)。音声了解度を表す客観指標 (SIIB, HASPI, ESTOI) については、 S a / M a から S b / M b へと雑音をより多様にすると若干値が低下しましたが、 L a から L b への変化については、値が同程度か若干の上昇にとどまりました。音声品質を表す客観指標 (PESQ, ViSQOL) については、 S a から S b へと雑音をより多様にすると値が大きく上昇しましたが、 M a / L a から M b / L b へと変化させた場合は、評価セットや客観指標によるものの、値はおおむね同程度にとどまりました。 図6 各条件における ( S a , S b ) の組合せに対する客観評価値 図7 各条件における ( M a , M b ) の組合せに対する客観評価値 図8 各条件における ( L a , L b ) の組合せに対する客観評価値 考察 汎化性能 評価セット間の客観評価値には、非常に強い相関が見られました。これは、音声データの量および多様性、雑音の多様性の変化によらず、異なる系統の雑音に対するモデルの性能変化の傾向が類似していることを示しています。雑音種類オープンの評価セット ( T acoust , T crowd , T office ) に対する客観評価値が雑音種類クローズド ( T closed ) の評価セットに対する客観評価値を上回ったことをあわせて考えると、 NELE-GANが雑音の種類に対して高い汎化性能を持っている ことが示唆されます。 音声データの量および多様性を変化させたときの音声了解度や音声品質の変化 音声データの量および多様性を変化させたときの音声了解度や音声品質の変化については、興味深い傾向が見られました。すなわち、比較的小規模の音声データを用いて学習した場合 ( S a / S b ) でも音声了解度は十分に向上しましたが、音声品質は大きく劣化してしまいました。そこからデータの規模を大きくすると、一旦は音声了解度が若干低下する一方で、音声品質はかなり回復しました ( M a / M b )。さらにデータの規模を大きくすると、音声品質をおおむね保ちつつ、音声了解度が回復またはさらに向上することが分かりました ( L a / L b )。このことから、 非常に大量かつ多様な音声データを用いてNELE-GANを学習することで、比較的少量のデータを用いて学習する場合よりも、モデルの性能を向上させることができる と言えるでしょう。 雑音の多様性を変化させたときの音声了解度や音声品質の変化 雑音の多様性を変化させたときの音声了解度や音声品質の変化は、音声データが比較的小規模の場合は顕著に差がありましたが、より大規模であるほど差は少なくなりました。この理由については、本実験の結果からだけでは推測が難しく、さらなる検討を必要とします。 結論 本記事では、NELE-GANをより大量かつ多様な音声データを用いて学習したときのモデル性能の変化を検証しました。同時に、音声に重畳する雑音についても、その多様性を変化させたときのモデル性能の変化を検証しました。結果として、 非常に大量かつ多様な音声データを用いることで、比較的少量のデータを用いる場合とくらべて、音声了解度を同程度に保つかさらに向上させた上で、音声品質を大幅に向上させられる ことが明らかになりました。 さらに大規模な音声データを用いた場合のモデル性能がどうなるのか気になりますが、それは今後の課題とします。 発表文献 加藤集平, & 橋本泰一 (2022). NELE-GANの学習に用いる音声データ量および多様性の影響についての調査. 日本音響学会2022年春季研究発表会講演論文集 , 1025–1028. 参考文献 Glasberg, B. R., & Moore, B. C. J. (1990). Derivation of auditory filter shapes from notched-noise data. Hearing Research , 47(1–2), 103–138. https://doi.org/10.1016/0378-5955(90)90170-T Hines, A., Skoglund, J., Kokaram, A. C., & Harte, N. (2015). ViSQOL: An Objective Speech Quality Model. EURASIP Journal on Audio, Speech, and Music Processing , 2015(13), 1–18. Jensen, J., & Taal, C. H. (2016). An Algorithm for Predicting the Intelligibility of Speech Masked by Modulated Noise Maskers. IEEE/ACM Transactions on Audio, Speech, and Language Processing , 24(11), 2009–2022. https://doi.org/10.1109/TASLP.2016.2585878 Kates, J. M., & Arehart, K. H. (2014). The Hearing-Aid Speech Perception Index (HASPI). Speech Communication , 65, 75–93. https://doi.org/10.1016/j.specom.2014.06.002 Kuyk, S., Kleijin, W. B., & Hendriks, R. C. (2018). An Instrumental Intelligibility Metric Based on Information Theory. IEEE Signal Processing Letters , 25(1), 115–119. https://doi.org/10.1109/LSP.2017.2774250 Li, H., & Yamagishi, J. (2021). Multi-Metric Optimization using Generative Adversarial Networks for Near-End Speech Intelligibility Enhancement. IEEE/ACM Transactions on Audio, Speech, and Language Processing , 29, 3000–3011. https://doi.org/10.1109/TASLP.2021.3111566 Lombard, É. (1911). Le signe de l'élévation de la voix. Annales des Maladies de L'Oreille et du Larynx , XXXVII(2), 101–109. Reddy, C. K. A., Beyrami, E., Pool, J., Cutler, R., Srinivasan, S., & Gehrke, J. (2019). A Scalable Noisy Speech Dataset and Online Subjective Test Framework. Proc. INTERSPEECH , 1816–1820. https://doi.org/10.21437/Interspeech.2019-3087 Rix, A. W., Beerends, J. G., Hollier, M. P., & Hekstra, A. P. (2001). Perceptual Evaluation of Speech Quality (PESQ) — A New Method for Speech Quality Assessment of Telephone Networks and Codecs. Proc. IEEE International Conference on Acoustic, Speech, and Signal Processing (ICASSP) , II, 749–752. https://doi.org/10.1109/ICASSP.2001.941023 芝慎太朗, 橘亮輔, & 岡ノ谷一夫 (2015). ジュウシマツの歌発声におけるロンバード効果と基本周波数の変化. 情報処理学会研究報告 , 2015-MUS-107(37), 1–3. *1 : もっと言えば、人間以外の動物でもロンバード効果が観察されることがあることが知られています(芝慎太朗ほか, 2015)。 *2 : 音声強調という言葉は、雑音や残響が混ざった音声信号においてそれらを抑制することを指すことが多いです。 *3 : 具体的には、あらかじめビン数を固定したequivalent rectangular bands (ERB) (Glasberg & Moore, 1990) 尺度に基づくフィルタバンクの各ビンに対する重み付けを行います。 *4 : モデルが特定の場面に限らず広い場面で高い性能を発揮すること。ここでは、どのような声あるいはしゃべり方の人でも聞き取りやすい声に変換できることを指しています。 *5 : Signal to noise ratio(S/N比、信号対雑音比)。信号(ここでは音声信号)のパワーの雑音のパワーに対する比で、値が小さいほど雑音が大きいことになります。 *6 : 音声データの学習・検証セット S に雑音データの学習・検証 セット( a または b )を重畳したものを、雑音の種類、音声サンプル(ランダムな識別子を付与)の順にソートして並べ、前半の320サンプルを S / M / L 共通の検証セットとしました。 *7 : Li & Yamagishi (2021) では16 kHzでしたが、本実験に用いた音声は電話の通話音声であるため、標本化周波数は電話の音声信号を符号化する際に用いられる8 kHzに制限されます。
アバター
こんにちは。はじめまして。PBX チーム所属の山崎です。 はじめに さてみなさま、夏休みはいかがお過ごしでしょうか。 夏休みで子どもがずっと家にいると、WEB 会議に乱入してくる可能性が高くなります *1 。 「おとーさーん!おとーーさーーん!あれ〜いないの〜〜?」「ちょっと静かにしててー💢」みたいなご経験、ないでしょうか。 もちろん乱入してきたからといってどうということはなく、同僚のそんな様子はむしろ和むのでウェルカムですが、自分がその立場になるとやはり気まずいものがあります。 そんな折、同僚が ON AIR ライト を買っていて、良さそうだったので自分も買ってみました。 しかしながら、日に数回とはいえ都度付け消しするのは面倒です。そこで、自動で on/off するようにしてみました。 前書きが長くなりましたが、今回の記事は MacBook のヘッドセットの接続/切断イベントを契機に、 ライトを自動で on/off して、 家族にミーティングの開始/終了を伝える というものを作ってみた、というご紹介になります。 お買い物 今回、製作するにあたって以下を使用しました。 スマートプラグ TP-Link Tapo P105 を使用しましたが、API が公開されていません もしこれから購入するのであれば、API ドキュメントが充実している SwitchBot プラグミニ が良さそうに思います ON AIR ライト 常時スイッチオンの状態にできる (スマートプラグで操作できる) ものであれば、なんでも OK です ヘッドセット MacBook (Monterey) 無線LAN 今回はスマートプラグと ON AIR ライトの組み合わせで製作しましたが、macOS からコマンドで操作できるものであればなんでも構いません。 ヘッドセット接続・切断イベントの検知 自動化するにあたって悩ましいのは、何をトリガーにするかという点です。 私はミーティング時のみ Apple EarPods with 3.5 mm Headphone Plug を MacBook に挿しているので、これをトリガーにすることにしました。 実はここが一番苦労したところでして、Apple 社のドキュメントのどこを見ても、オーディオデバイスの接続・切断の検知方法が書いてありません (調べきれていないだけかも) 。 ブラウザなら MediaDevices の devicechange イベント を拾えばサクッと終わりますが、これだけのために1プロセス常駐させるのももったいない話です(貧乏性なんです)。 また、 system_profiler コマンドで接続中のデバイス一覧がとれるので、これを例えば 「5 分に 1 回実行して状態を検出」でもいいのですが、これもなんだかもったいないですし、最大5分遅延してしまうので、嬉しくありません。 それっぽいアプリもなく煩悶としていたところ、システム環境設定の「サウンド」の項目が変化することに気付きました。 システム環境設定は /Library/Preferences/ 以下に設定を保存するので、それっぽいファイルを漁ってみます。 すると、抜き差しのタイミングで /Library/Preferences/Audio/com.apple.audio.SystemSettings.plist が更新されることがわかりました。そして、ファイルの変更イベントは launchd で検出できます。これで勝ち筋が見えました。 やってみよう ファイルを2つ、作成します。実際のファイル名は適宜環境に合わせて読み替えてください。 ~/Library/LaunchAgents/com.example.on-air.plist /path/to/on-air.sh まず ~/Library/LaunchAgents/com.example.on-air.plist を作成します: <? xml version = "1.0" encoding = "UTF-8" ?> <! DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" > <plist version = "1.0" > <dict> <key> Label </key> <string> com.example.on-air </string> <key> WatchPaths </key> <array> <string> /Library/Preferences/Audio/com.apple.audio.SystemSettings.plist </string> </array> <key> ProgramArguments </key> <array> <string> /path/to/on-air.sh </string> </array> </dict> </plist> ここでは、 WatchPaths で指定したファイルに変化があったら、 ProgramArguments を実行する という処理をしています。 次に、 on-air.sh を実装していきます。このファイルには実行権限の付与( chmod +x on-air.sh )をしておきます。 #!/bin/sh # "system_profiler -json SPAudioDataType" コマンドで表示される、お手元のデバイスの名前にあわせてください AUDIO_DEVICE_NAME = ' 外部マイク ' JQ =/opt/homebrew/bin/jq connected () { osascript -e ' display notification "ON AIR: connected" ' } disconnected () { osascript -e ' display notification "ON AIR: disconnected" ' } # 切断中 or 接続中を判断する system_profiler -json SPAudioDataType | \ $JQ -e " .SPAudioDataType[]._items[] | select(._name == \" $AUDIO_DEVICE_NAME \" ) " > /dev/null if [ $? == 0 ]; then connected else disconnected fi launchd からは接続・切断を見ずに、単に設定ファイルの更新イベントだけを拾って on-air.sh を呼びます。 そこで、 on-air.sh の中で接続 or 切断を判断しています。 2つのファイルを作成できたら、以下のコマンドで launchd に設定を読み込みます: $ launchctl load ~/Library/LaunchAgents/com.example.on-air.plist この状態でヘッドセットを抜き差しすると、通知センターに connected/disconnected が出力されます(数秒のタイムラグがあります)。 あとは connected()/disconnected() の部分を実装して、ライトの on/off を制御できるようになったら完成です。 ライトのon/off 実際に on/off する処理を書いていきます。 今回使用したスマートプラグ Tapo P105 は API 仕様が公開されていません。 適当にググっていくつか試したところ、 fishbigger/TapoP100 がいい感じに動いたので、ありがたくこれを利用することにします。 *2 3つ目のファイル、 tapo-p105.py を作ります: #!/usr/bin/env python3 import sys from PyP100 import PyP100 ipaddress, email, password, onoff = sys.argv[ 1 :] p105 = PyP100.P100(ipaddress, email, password) p105.handshake() p105.login() if onoff == "on" : p105.turnOn() elif onoff == "off" : p105.turnOff() この Python スクリプトを使って、先ほどの connected()/disconnected() の部分を以下のように書き換えます。 SCRIPT_DIR =/path/to/tapo-p105 PYTHON = " $SCRIPT_DIR /venv/bin/python3 " IP = 192 . 168 . 0 . 2 # スマートプラグの IP アドレス P105_EMAIL = " your-account@example.com " P105_PASSWD = " your password " connected () { $PYTHON " $SCRIPT_DIR /tapo-p105.py " " $IP " " $P105_EMAIL " " $P105_PASSWD " on } disconnected () { $PYTHON " $SCRIPT_DIR /tapo-p105.py " " $IP " " $P105_EMAIL " " $P105_PASSWD " off } 最後に、TapoP100 ライブラリをインストールします: cd /path/to/tapo-p105 python3 -m venv venv source venv/bin/activate pip3 install PyP100 これで完成です。 ヘッドセットを接続してライトを点灯したところ むすびに 実は春休みに作って 4 ヶ月ほど運用してきました。実際に使ってみると、いい感じに QoL が上がりました。 WEB 会議中に割り込まれることが少なくなって快適 (家族からは) 話しかけて大丈夫なタイミングがわかるようになって、ストレス軽減と好評 子どもから、お父さんすごーい!とピュアな尊敬を得られる 一方、抜くのを忘れてて夕ご飯に呼ばれず、一人寂しく食べる羽目になったこともありました。 技術の過信は良くないですね(大げさ)。 *1 : RevComm ではフルリモート制度を導入していまして、普段のミーティングは基本的にオンラインで行われます *2 : Tapo P105 はファームウェアバージョンによって API の仕様が異なるらしく、試した他のライブラリは動作しませんでした。
アバター
はじめに:アップデートできていますか? 作ったきりで一度もライブラリをアップデートしていない、そんなプロダクトも多いのではないでしょうか。新規ライブラリの利用が古いライブラリへの依存により実現しないことなど、損失が発生するケースは多々あります。脆弱性対策のアップデートをして、新たな不具合を発生させていては本末転倒です。それらを理解していても、必要に迫られるまでアップデートは後回しにされることが多いと思います。しかし、アップデートが必要になった時には大規模アップデートとなり、エラーと隣り合わせの状態で、祈りながらリリースされることも多いのではないでしょうか? 本記事では Dependabot、GitHub Actions、Sentry を利用してアップデートを半自動化し、実現可能な工数で祈らず継続的にアップデートする手法を提案します。 本記事のまとめ 以下の 3 ステップでの継続的なアップデートを提案します。 情報を集める:Dependabot を設定する アップデートを検証する:ビルド差分を比較する 監視する:Sentry でエラーを検知する 情報を集める:Dependabot を設定する まず、アップデート情報を定期的に取得する必要があります。これに関しては優れた解決策がすでに用意されています。筆者のチームでは GitHub 公式の Dependabot を利用することにしました。Dependabot は更新を通知してくれるだけではなく、リリースノートが記載されたアップデート Pull Request の作成まで行ってくれます。 Bump TypeScript 公式 https://docs.github.com/ja/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates アップデートを検証する:ビルド差分を比較する Dependabot が Pull Request を作成してくれるとしても、全ての Pull Request のリリースノートを読み影響範囲を特定しテストを行うとすると、検証にかなり多くの工数を割くことになります。 そこで、コードベースでアップデートを検証する仕組みを整え、一部のアップデートについては自動検証を可能にしました。 フロントエンドではユーザーに配信するファイル(ビルド成果物)が全く同じであれば、リグレッションが発生しないことの証明になります。さらに、多くのビルド環境では Tree shaking (Dead Code Elimination) の仕組みがあり、ライブラリの利用していない部分の変更に関しては、ビルド成果物には反映されません。つまり、実際には多くのライブラリアップデートはビルド成果物をコードベースで比較し差分がないことをもって検証を完了できるのです。 *1 筆者のチームでは Dependabot の作成した Pull Request に対して、アップデート前後のビルド成果物を比較する CI を設定し、それが通過していればそのままリリースに進める運用としました。実際にチームのプロダクトでは 120 件あったマイナーアップデートの内、73 件は差分が生じておらず、人力での検証をスキップしてリリースできました。 実際には GitHub Actions で以下のように実装しました。 *2 name : Dependabot diff on : push : branches : - 'dependabot/npm_and_yarn/**' jobs : diff : timeout-minutes : 10 if : github.actor == 'dependabot[bot]' runs-on : ubuntu-latest steps : - uses : actions/setup-node@v3 with : node-version : '16' # アップデート後のビルド - uses : actions/checkout@v3 with : ref : ${{ github.ref }} - name : Install run : | npm ci - name : Build run : | npm run build mv build /tmp/head # アップデート前のビルド - uses : actions/checkout@v3 with : ref : main - name : Install run : | npm ci - name : Build run : | npm run build mv build /tmp/base # 比較 - name : Diff run : | diff -r /tmp/head /tmp/base 監視する:Sentry でエラーを検知する 実際に運用してきた中で、リリースノートを読み影響範囲を調査し修正を加えたとしても、エラーがないことの確証を得られないケースは多くありました。また、Tree shaking 可能な形で配信されておらずアップデートの度に差分が生じてしまうライブラリも多いです。そこで、そのようなアップデートに関しては、社内環境にリリースして1週間程度監視した後、新規エラーが検出されていないことを確認できれば社外向けにリリース可とする運用にしました。 エラー検知には Sentry を使用しました。設定すればアプリケーション内で発生したエラーを検知して送信、集計、レポートを作成することまで自動化することができます。 参考: docs.sentry.io techblog.cartaholdings.co.jp おわりに 以上、祈らないアップデートを提案しました。筆者のチームでは、実際にこれらの仕組みを導入してから半年以上継続的にアップデートが行われています。一部メジャーバージョンの更新を除き、ほとんどのライブラリが最新になっています。 継続的なアップデートを! *1 : Dev dependencies も成果物に影響を与えないことが多いです。アップデートで知らないうちに開発環境を壊してしまうと困るので、しっかり Formatter や Linter も CI で実行するようにしています。 *2 : pull_request をトリガーにした場合ビルド対象を base head の変数で参照可能です。しかし、全ての Pull Request に反応して Action が起動されスキップしたログが残るのが気になったので、トリガーはブランチ名フィルタを指定することにしました。
アバター
こんにちは、RevComm にて主に MiiTel の音声解析機能に関する研究開発を担当している石塚です。 石塚賢吉(いしづか けんきち) プリンシパルリサーチエンジニア。筑波大学大学院博士後期課程卒業。博士(工学)。日本HP株式会社にて通信事業者向けのシステム開発、株式会社ドワンゴで全文検索システムの開発などに従事。2019年12月、株式会社RevComm入社。音声認識、音声感情認識、全文検索システムの研究開発を行なっている。 → 過去記事一覧 RevComm では、電話営業やお客様対応を可視化する音声解析 AI 搭載型のクラウド IP 電話 MiiTel (ミーテル) を提供しています。 2022年2月9日、その MiiTel に音声感情認識機能を追加しました。 prtimes.jp これによって話し手のポジティブ、ネガティブな感情が可視化され、会話の当事者以外でも感謝を伝える様子やクレームなどに気づくことができます。 弊社プロダクト「MiiTel」画面 (抜粋) ビジネスの電話応対について、話者の発話音声の感情の側面からの解析を可能とするため、RevCommでは音声感情認識の研究を重ねてきました。成果の一部は国立大学法人筑波大学との共同研究による音声感情認識に関する論文として、2021年8月に音声処理系トップカンファレンス「INTERSPEECH 2021」にて発表しています。 今回は、INTERSPEECH 2021で発表した論文 「Speech Emotion Recognition based on Attention Weight Correction Using Word-level Confidence Measure」 について解説します。 1. はじめに 2. 提案手法 2.1 提案アルゴリズムのベースとなる音声感情認識器の構造 2.2 単語信頼度とは 3. 評価実験 4. まとめ 5. 参考文献 1. はじめに  深層学習技術が発展し、時系列データを扱うリカレントニューラルネットワークや Self-Attention による重み付けの技術が音声からの特徴抽出に有効に機能し、音声感情認識の性能が向上してきました [Mirsamadi, 2017]。また、音声認識により得られたテキストと音響特徴量の両方を利用して、高精度な音声感情認識を達成しようとする研究もあります。  しかし、音声認識による文字起こしの精度はまだ十分とは言えません。特に、文法が崩れがちな感情を含む音声を音声認識で正確に文字起こしするのは困難です。そこで、音声感情認識モデルと事前学習された音声認識モデルを End-to-end で結合し、感情音声データセットを用いたマルチタスク学習でファインチューニングすることで、認識精度を向上する方法などが提案されています [Feng, 2020]。しかしこの方法では、感情音声データセットに対して音声認識と音声感情認識を行うモデル全体をファインチューニングするために計算コストがかかります。本研究では、音声認識により得られるテキストの信頼度の情報を用いて、音声認識の誤りの影響を軽減しながら音声感情認識を行うための手法を提案します。 2. 提案手法 2.1 提案アルゴリズムのベースとなる音声感情認識器の構造  図1に提案アルゴリズムのベースとなる、テキスト情報と音響情報を用いた音声感情認識器の構造を示します [Mirsamadi, 2017] 。本音声感情認識器は、音響特徴抽出器、テキスト特徴抽出器、そして2つの抽出器の出力を組み合わせて最終的な分類を行う感情分類器の3つから構成されています。本アルゴリズムでは、まず発話音声から音響特徴量とテキスト特徴量を抽出します。次に、音響特徴量を BiLSTM に入力し、Self-Attention を用いて重み付けを行い、中間表現を得ます。テキスト特徴量は、Word-Embedding によりベクトル化し、 音響特徴量と同様に処理します。最後に、中間表現を連結し、完全連結ネットワークで分類することで、最終的な感情クラスが出力として得られます。  本研究では、この音声感情認識器の構成をベースとし、Self-Attentionの重みを単語レベルの単語信頼度で補正することで、音声認識時に誤認識された単語に Self-Attention で注目する事を防ぎ、音声感情認識精度の向上を目指します。 図1. ベースとなる音声感情認識器の構成 2.2 単語信頼度とは  単語信頼度とは、音声認識結果の単語ごとの信頼度を0.0 - 1.0の値で表現したものです。表1に、正解文の単語と音声認識結果の単語と単語信頼度の例を示しています。表1の赤で塗りつぶされた箇所は誤認識された単語で、基本的には、誤認識された単語の信頼度は低くなる傾向があります。ただし、黄色で塗りつぶされた箇所のように、正しく認識された単語の場合でも信頼度が低くなることがあります。 表1. 単語信頼度の例 正解文 I NEED YOUR BIRTH CERTIFICATE 音声認識結果 (単語信頼度) I (1.0) READ (0.5) YOUR (0.3) BURST (0.4) CERTIFICATE (1.0)  音声感情認識のテキスト特徴量として単語信頼度を用い、誤って認識された単語の影響を抑制したり、正しく認識された単語の影響を強調したりすることを考えます。本論文では、テキスト特徴抽出器での単語信頼度の利用方法として、図2のような3つの構成で単語信頼度の有効性を比較します。 Proposed (a) Early fusion method: 単語信頼度をテキストの特徴量と組み合わせて、テキスト特徴量の一部として使用する構成 Proposed (b) Late fusion method: 単語信頼度を中間特徴量と組み合わせて使用する構成 Proposed (c) Confidence Measure (CM) as weighting correcting: 単語信頼度をアテンション重みと組み合わせて使用する構成です。こちらは、前の二つの構成に対して、単語信頼度のテキストの特徴に対する依存が小さくなることが期待されます 図2. テキスト特徴抽出器での単語信頼度の利用方法  次に、Proposed (c) の構成において、単語信頼度がアテンションの重みに対してどのように作用するかについて図3を例に説明します。図3において、横軸は時間軸となっており、音声認識結果のテキストが下部に示されています。上から一番目の折れ線グラフは、補正前の単語に対するアテンションの重みを表現したものです。二番目は、単語信頼度であり、黄色で塗りつぶされた部分に音声認識誤りの単語列があったとして、その部分の単語信頼度が低くなっています。三番目は、補正後のアテンションの重みです。このとき、音声認識の誤り部分のアテンションの重みが、単語信頼度で補正され、小さくなっていることがわかります。逆に、単語信頼度の大きな部分のアテンションの重みは、大きくなります。 図3. 単語信頼度のアテンションの重みに対する作用 3. 評価実験  本研究では、感情認識のベンチマークデータセットの一つである Interactive Emotional Dyadic Motion Capture (IEMOCAP) データセット[Busso, 2008] を利用して、提案手法の有効性を評価します。IEMOCAP データセットでは、合計10人の話者(男性5人、女性5人)による各発言に対し、人手での書き起こしテキストと7つの感情(幸せ、悲しい、中立、怒り、興奮、欲求不満、その他)ラベルのどれかが1つ付与されています。評価実験では 5-fold cross validation を行い、話者の独立性を確保しながら音声感情認識の精度を評価します。 表2. 手法の比較 Method             UA     WA     Speech 61.1 64.3 Text (Transcript) 75.5 75.6 Text (ASR) 71.8 71.9 Speech + Text (Transcript) 78.6 78.4 Speech + Text (ASR) 73.9 74.2 Our Proposed Method Proposed (a) 74.3 74.4 Proposed (b) 74.9 75.4 Proposed (c) 75.9 76.1  使用する特徴量の組み合わせを変えた音声感情認識の実験結果を表 2 にまとめています。IEMOCAP データに対する音声認識テキストの Word Error Rate(WER)は43.5%でした。音声感情認識の評価指標として、先行研究に従い、Unweighted Accuracy(UA)および Weighted Accuracy(WA)を採用していますが、両評価指標は類似した傾向を持つため、主にWAを用いて結果を分析します。  音声のみを用いたとき [Speech] の WA 値は64.3%であり、人手での書き起こしのみを用いたとき [Text(Transcript)] の WA 値は75.6%となりました。音声と人手での書き起こしテキストを組み合わせたとき [Speech+Text(Transcript)] の WA は78.4%であり、音声のみ [Speech] よりも14.1%、人手で書き起こしたテキストのみ [Text(Transcript)] よりも2.8%上回りました。一方、人手で書き起こしたテキストを使う代わりに音声認識結果を用いると [Text(ASR)]、WA が3.7%低下することがわかりました。  音声と音声認識結果の組み合わせ [Speech+Text(ASR)] では WA が74.2%となり、4.2%の性能劣化となりました。  単語信頼度をテキスト特徴量に組み込む手法として提案した Proposed (a): Early fusion、Proposed (b): Late fusion、Proposed (c): CM as weighting correcting については、それぞれ74.4%、75.4%、76.1%のWAが得られました。提案した手法のうち Proposed (c): CM as weighting correcting は、[Speech+Text(ASR)] からの性能向上が最も大きく、音声と人手での書き起こしテキストを組み合わせた手法の結果に最も近い性能を示しています。これは、単語信頼度でアテンションの重みを調整し、誤っている可能性の高い音声認識結果の単語の重要度を下げることで、性能向上が実現できることを示唆しています。 表3. 先行研究の実験結果と本研究の実験結果の比較  IEMOCAP データセットを用いた先行研究の実験結果と本研究の提案手法の実験結果の比較を表3にまとめています。提案手法は、最も高い UA と WA を達成しました。 4. まとめ  本研究では、音声認識により得られるテキスト情報と単語レベルの信頼度を利用する音声感情認識手法を提案しました。そして、感情音声データセット IEMOCAP を用いて、単語信頼度により音声認識テキストの音声認識誤りの影響を軽減する手法について検討しました。提案した3つの手法のうち、単語信頼度をSelf-Attentionの重みの補正として用いる方法が最も良い性能を得ることができました。そして、IEMOCAP データセットを用いた先行研究の多くと比較して、提案手法がより良い性能を示すことがわかりました。  「Speech Emotion Recognition based on Attention Weight Correction Using Word-level Confidence Measure」の本文はインターネット上で無料公開されているので、詳しくは こちら をご覧ください。また、RevComm では ICASSP(International Conference on Acoustics, Speech, & Signal Processing)2022でも京都大学との音声感情認識についての共同研究の成果を発表しておりますので、興味があればぜひ こちら もご覧ください。こちらの研究では、マルチタスク学習を用いて、RevCommが保有するビジネス電話応対の自然な感情音声データセットと、演技された感情音声のデータセットを組み合わせて、より効果的に音声感情認識モデルを学習する手法について提案しています。  今後も、共同研究で得られた成果をもとに音声感情認識モデルを強化し、弊社プロダクトに組み込むことで、お客様の感情の可視化や、お客様の不満を示す対話の抽出と解析などへの応用に取り組んでいきます。RevComm は AI 技術領域にイノベーションをもたらし、コミュニケーションをより豊かにしていくことを目指しています。そのために、今後も音声・言語・画像の領域に関わる研究開発を推進し、国内外へ積極的に学術的な貢献を行っていきます。 5. 参考文献 [Mirsamadi, 2017] S. Mirsamadi, E. Barsoum, and C. Zhang, “Automatic Speech Emotion Recognition Using Recurrent Neural Networks with Local Attention,” Proc. ICASSP, pp. 2227-2231, 2017. [Feng, 2020] H. Feng, S. Ueno, and T. Kawahara, “End-to-End Speech Emotion Recognition Combined with Acoustic-to-Word ASR,” Proc. Interspeech pp. 501–505, 2020. [Busso, 2008] C. Busso, M. Bulut, C. Lee, A. Kazemzadeh, E. Mower, S. Kim, J. N. Chang, S. Lee, and S. S. Narayanan, “IEMOCAP: Interactive Emotional Dyadic Motion Capture Dataset,” Language Resources and Evaluation, vol. 42, no. 4, pp. 335-359, 2008.
アバター