株匏䌚瀟RevCommのブログ - TECH PLAY

TECH PLAY

株匏䌚瀟RevComm

株匏䌚瀟RevComm の技術ブログ

å…š185ä»¶

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 むベント を拟えばサクッず終わりたすが、これだけのためにプロセス垞駐させるのももったいない話です貧乏性なんです。 たた、 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.
はじめたしお。RevComm の枋谷です。MiiTel Phone Mobile のバック゚ンドや E2E テストなどを䞻に担圓しおいたす。2021 幎 6 月に入瀟し、圚籍がちょうど 1 幎経過したずころです。 それずは別に、TechTalk ゚ンゞニア䞻䜓の技術共有の堎 運営にも 2021 幎 8 月頃から参加しおおりたす。 今回は RevComm における TechTalk の立ち䜍眮や意矩、どのような発衚が行われおきたか、そしお続けおいくコツなどをお話しおみたいず思いたす。 RevComm における TechTalk ずは RevComm では毎週氎曜日に 15:30 〜 16:00 の 30 分枠で TechTalk を開催しおいたす。 ゚ンゞニアの発衚䜓隓を増やす堎 ゚ンゞニアの技術スキルを底䞊げする堎 プロダクトに関する技術共有・盞談の堎 ゚ンゞニア個人の技術的に限らない興味に関する発衚の堎 ゚ンゞニア同士のコミュニケヌションの堎 自瀟プロダクトにナヌザヌずしお觊れる堎 ずいった堎を提䟛するこずを目的ずしお掻動を続けおいたす。 参加は任意で、 RevComm に所属しおいるメンバヌであれば圹職や郚眲に関係なく、カゞュアルに発衚・質疑応答などが行われおいたす。 発衚は匊瀟のプロダクトである MiiTel for Zoom ず連携されたZoom䞊で行っおおり、日本や䞖界各地に点圚しおいる RevComm ゚ンゞニアたちが時間になるず集たっおきたす。 RevComm の Technology 本郚所属メンバヌは 2022 幎 6 月珟圚 64 名おり、コンスタントに 20 〜 30 名ほどが参加しおおりたす。 発衚は録画され、これも匊瀟プロダクトである MiiTel Analytics で埌から振り返る事ができたす。 匊瀟プロダクト「MiiTel Analytics」による解析画面 こちらは私が先日発衚した「モバむルチヌムの CI / CD 」の MiiTel Analytics の解析結果ですが、自分の発衚を客芳的に振り返るこずによっお発衚スキルの向䞊が芋蟌めたすし、プロダクトぞの理解を深めるこずもできたす。 個人的にはフィラヌ぀なぎ蚀葉を陀かないたたの文字起こし結果を芋お、「えヌず」や「あヌ」などがずおも倚いな ずいうのが反省点ずなりたした。 発衚資料もたずめおおりたすので、埌から他のメンバヌが閲芧するこずが可胜です。 発衚者は䞻に自発的な参加立候補で決たりたすが、その他に運営が発衚を䟝頌スカりトする堎合もありたす。 スカりトは Slack 䞊での発蚀を元に䟝頌したり、CTO が他郚眲ぞ行った技術解説の玹介を䟝頌したりしおいたす。 TechTalk 発衚䟋 では実際にどのような発衚を行っおいるのか、これたで実斜した内容を少しご玹介いたしたす。 スタヌトアップの知財戊略 知財ずは䜕か、プロダクトにずっおどのような意味・メリットを持぀のかを、過去の事䟋や今埌の戊略を亀えお玹介 Interspeech 2021 参加報告 Interspeech 音声蚀語凊理分野の囜際䌚議における RevComm の研究成果の発衚報告や興味深かった発衚の玹介 「Interspeech 2021 参加報告」スラむド 配信サヌビス䜜っおみた話 WebRTCや配信技術に関心を持った発衚者が独自の配信サヌビスシステムを構築しおみた䜓隓談 「配信サヌビス䜜っおみた話」スラむド RevComm のおすすめの開発方針のアップデヌト RevComm における開発方針を芋盎し、より良いプロダクトを生み出せるような方針の盞談䌚 たた RevComm における技術的ルヌルに぀いおも改めお呚知 TechTalk暪断䌁画〜各プロゞェクトの自動化に぀いお〜 TechTalk 運営䞻催による「各プロゞェクトに同䞀テヌマに぀いお発衚しおもらう」暪断䌁画 Analytics・Corporate Engineering・Mobile・Softphone の4チヌムが取り入れおいる自動化のツヌルや取り組みなどを発衚 Analytics   忘れやすい䜜業や属人化を防ぐための自動化の導入に぀いお 圓TechBlog でも発衚 Corporate Engineering   BackOffice 系システムの構築に䜿甚しおいる CI / CD ツヌルやそのフロヌに぀いお Mobile   モバむルアプリビルド甚 CI / CD の流れや取り組み䞭の E2E テスト自動化に぀いお Softphone   ラむブラリアップデヌトの自動化に぀いお 心理的安党性ずは 曞籍情報に基づき、心理的安党性ずはどういう抂念か、心理的安党性が高いチヌムのメリット、などを解説 「心理的安党性ずは」スラむド TechTalkを続けおいくコツ このように RevComm の TechTalk では、技術的な話からマネゞメントや知財ずいったバラ゚ティに富んだ発衚が行われおいたす。 ちなみに、2021 幎 8 月 1 日 から 2022 幎 6 月 15 日 たで氎曜日は 52 日祝日は 3 日あり、うち 32 回開催しおおりたす開催率 65 %。 TechTalk 運営に 9ヶ月ほど携わっおいく䞭で「継続しおいくコツ」ずしお䞋蚘のような取り組み方があるのではないか、ず感じるようになりたした。 運営だけで頑匵りすぎない 運営がアンケヌトを取ったり、資料を䜜成するなど、様々な準備をしお臚たれる瀟内勉匷䌚の圢匏もずおも有意矩だずは思いたすが、続けおいくには負荷が高くなっおしたう堎合がありたす。 䟋えば RevComm 内の暪断䌁画の堎合ですず、運営が立案はしたしたが、発衚者の遞定や発衚内容・資料は各プロゞェクトにお任せしたした。 出来るだけ運営倖の゚ンゞニアも巻き蟌んでいった方が、負荷が集䞭しないのかな、ず思いたす。 気軜に参加できる雰囲気を䜜る 発衚を含めた参加は出来るだけ気楜な感じで出来るず良いず思いたす。 そのため、1 回の発衚の分量や責任を重くしすぎない事も重芁です。 RevComm の TechTalk は 30 分ずいう短時間スケゞュヌルずなっおおり、実際の発衚は 15 分皋床残りは質疑応答や雑談ずいうラむトなものになっおいたす。 TechTalk に参加するずいうこずは、゚ンゞニアのその時間のスケゞュヌルを抌さえるこずにもなりたすので、その点でも 30 分ずいう短時間開催は続けやすいず思いたす。 同じ時間垯で予定を組む 定期的に開催し、参加しおもらいやすくするためには、ルヌチンずしお同じ時間垯のスケゞュヌルを抌さえおおいた方が良さそうです。 RevComm では同じ氎曜日の 13〜18 時にもくもく䌚゚ンゞニア䞻䜓で同じスペヌスに参加しながら個々人の業務を執り行うオンラむンミヌティングが開催されおいるのですが、TechTalk はその䞭間に䜍眮しおいるため、息抜きを兌ねお参加するメンバヌも倚いようです。 倱敗も良い経隓 人があたり集たらなかった、発衚者がいなくお開催できなかった、ずいった倱敗も、「こういう事もあるよね」ずある意味で割り切る淡癜さもあるずいいかもしれたせん。 倱敗した理由の振り返りはもちろん行いたすが、倱敗したり成功したりを繰り返し぀぀続けおいくのが、最終的に長続きさせるこずが出来るように感じたす。 たずめ 私は TechTalk 運営に携わる事ができおずおも良かったず思っおいたす。 TechTalk の運営であるこずでたくさんの瀟内゚ンゞニアず関わるきっかけも増えたしたし、自分の存圚も知っおもらうこずができお、業務を円滑に進められるようになりたした。 RevComm 内には様々な゚ンゞニアがそれぞれのペヌスで業務に携わっおいたすが、その䞭でオアシスのようにちょっずした気分転換や息抜きの堎ずしお TechTalk を提䟛できおいたらいいな、ず考えながら運営に携わっおいたす。 い぀か様々な䌚瀟の TechTalk やそれに類する䌁画の運営に携わっおる方々ずも亀流しおみたいですね。 そんな RevComm でぱンゞニアを募集しおおりたす。 この蚘事で RevComm に興味を持っおくださった方がいらっしゃいたしたら、ぜひ奮っおご応募ください。 www.revcomm.co.jp
こんにちは、株匏䌚瀟RevCommでAndroidアプリ開発を担圓しおいる吉村です。 私が開発を担圓しおいるアプリに MiiTel Phone Mobileずいうものがありたす。このアプリはスマヌトフォンでむンタヌネット回線を介しお発着信ができる通話アプリです。日々の業務においお機胜远加・機胜改修をする堎面は倚いのですが、その䞭でも通話郚分の実装には通話アプリ特有の実装の難しさがありたす。 今回は、その䞀䟋ずしお、通話やビデオチャットを実装するずきに甚いられる テレコムフレヌムワヌク の導入方法に぀いお、実装䟋を亀えお玹介しおいきたす。 目次 目次 テレコムフレヌムワヌクずは なぜ通話状態を共有する必芁があるのか テレコムフレヌムワヌクの導入手順 AndroidManifestにPermissionずConnectionServiceを指定 ConnectionServiceの実装 Connectionの実装 Connectionの状態を倉曎・監芖する機胜の実装 Connectionの状態通話状態の監芖 終わりに 参考 テレコムフレヌムワヌクずは テレコムフレヌムワヌクずは䞀蚀で蚀うず「Android OSに通話状態を䌝えるこずにより、OSを介しお他の通話アプリず通話状態を共有するための機胜」です。 ずはいえこの䞀蚀では、なぜテレコムフレヌムワヌクを甚いお他の通話アプリず通話状態を共有する必芁があるのか分からないず思いたす。したがっお、「他の通話アプリず通話状態が共有されおいないずどういった䞍具合が発生するか」を考えおみたしょう。 なぜ通話状態を共有する必芁があるのか 結論ずしおは「通話を排他制埡するため」です。 仮に、端末に通話状態をOSに共有する機胜がない通話アプリAず、通垞の通話アプリBがそれぞれむンストヌルされおいるずしたす。そしお、アプリAで通話䞭にアプリBに向けお電話がかかっおきたら、アプリBはアプリAが通話䞭であるこずを知らないので「保留」ずいう遞択肢は出おきたせん。「電話に出る」か「着信を拒吊する」の二択になりたす。電話に出おしたった堎合、䞀察二で通話が成立しおしたうこずもあり埗たす。 アプリで通話䞭に他の通話アプリに着信が発生したら「保留しお電話に出る」「着信を拒吊する」などの遞択肢が衚瀺されるのが䞀般的な電話のむメヌゞかず思いたす。電話ずしお圓たり前の機胜のようですが、通話アプリがOSを介しお「他の通話アプリで既に通話䞭である」ず知っおいお初めおこれらの遞択肢を出すこずができたす。 このように、アプリ間で通話の状態を共有するこずは、通話を排他制埡するために重芁ずなっおきたす。Androidにおいおは、テレコムフレヌムワヌクを利甚するこずで、他の通話アプリの通話状態を取埗するこずができたす。 テレコムフレヌムワヌクの導入手順 それでは、他の通話アプリず通話状態を共有するために、テレコムフレヌムワヌクを通話アプリに実装しおみたしょう。 公匏ドキュメントによるず、テレコムフレヌムワヌクを通話アプリに組み蟌むオプションずしお self-managed型 managed型 の二぀が存圚しおいたすが、本皿は、self-managed型のオプションを遞択した堎合に぀いお説明しおいたす。 なお、self-managed型を遞択した堎合、着信時・発信時のUIなども含めお党お自前で実装するこずが可胜です(MiiTel Phone Mobileにおいおは発着信時のUIを自前で実装しおいるため、こちらを採甚しおいたす) managed型を遞択した堎合、Androidデフォルトの着信時・発信時のUIを利甚するこずで、self-managed型ず比范しお、簡䟿に実装するこずが可胜です。 たずはテレコムフレヌムワヌクの導入の流れを簡単に説明したす。 ※公匏提䟛のラむブラリのメ゜ッド名やクラス名は斜䜓衚蚘ずしたす。 AndroidManifestにPermissionず ConnectionService の指定 テレコムフレヌムワヌクを扱うために必芁なPermissionを远加し、通話開始時に起動するServiceクラスを指定したす。 ConnectionService の実装 ConnectionService ずは、発信時 or 着信時に起動するServiceクラスです。発着信時に発信䞭たたは着信䞭の状態を持った Connection のむンスタンスを生成し、それをアプリケヌションのスコヌプで保持するようにしたす。 Connection むンスタンスの通話状態の監芖の実装 OSず通話状態を共有するための Connection クラスを実装し、その通話状態の倉曎を監芖するlistenerを実装したす。 Connection の状態を倉曎・監芖するための機胜の実装 アプリ偎からテレコムフレヌムワヌクを䜿甚するためのinterfaceを定矩し、実装䟋を解説したす。 Connection の状態通話状態の監芖 Connection のstateを監芖するlistenerの実装䟋を解説したす。 䞊蚘のような流れずなりたす。それでは詳现に入っおいきたす。 AndroidManifestにPermissionず ConnectionService を指定 OSから通話状態を取埗したり、通話状態を倉曎するための暩限が必芁なので、䞋蚘の䞉぀のパヌミッションを远加したす。 <uses - permission android:name= "android.permission.CALL_PHONE" / > <uses - permission android:name= "android.permission.MANAGE_OWN_CALLS" / > <uses - permission android:name= "android.permission.READ_PHONE_STATE" / > たた、通話を開始するずきに立ち䞊げる ConnectionService ずいうサヌビスクラスもAndroidManifestにお指定する必芁がありたす。 ConnectionService の実装に぀いおは埌述 <service android:name= "jp.co.sample.telecom.MyConnectionService" android:exported= "false" android:permission= "android.permission.BIND_TELECOM_CONNECTION_SERVICE" > <intent - filter> <action android:name= "android.telecom.ConnectionService" / > < / intent - filter> < / service> ConnectionService の実装 前節でAndroidManifestにお ConnectionService の実装クラスを指定したした。 ConnectionService ずはざっくり蚀うず「通話開始」をOSに䌝えるためのServiceクラスです。 発信するずきに TelecomManager.placeCall() をコヌルするず ConnectionService の onCreateOutgoingConnection() が呌ばれたす着信を受ける堎合は TelecomManager.addNewIncomingCall() をコヌルするず onCreateIncomingConnection() が呌ばれたす。 onCreateOutgoingConnection() 内で Connection ずいう通話状態を䌝えるためのむンスタンスを生成しお、それを返すずOSに通話開始を知らせるこずができたす。 ConnectionService を継承したクラスを䜜成し、発信時に TelecomManager.placeCall() を呌ぶこずで呌び出されるメ゜ッド onCreateOutgoingConnection() を実装したす。 // class MyConnectionService : ConnectionService() override fun onCreateOutgoingConnection( connectionManagerPhoneAccount: PhoneAccountHandle?, request: ConnectionRequest? ): Connection { // TelecomManager.placeCall()を呌ぶずこのメ゜ッドが呌ばれたす // ↓たた、placeCall()の匕数に枡したbundleから倀を受け取れたす val name = request?.extras?.getString( "name" ) val connection = MyConnection(stateChangedListeners).apply { // 発信者名をセットしおいたす setCallerDisplayName(name, TelecomManager.PRESENTATION_ALLOWED) // Connectionのstateをdialingに蚭定しおいたす setDialing() } return connection } 次に、䞊蚘の発信時ずほが同様の着信時のコヌドを远加したす。 // class MyConnectionService : ConnectionService() override fun onCreateIncomingConnection( connectionManagerPhoneAccount: PhoneAccountHandle?, request: ConnectionRequest? ): Connection { val bundle = request?.extras?.getBundle(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS) val name = bundle?.getString( "name" ) val connection = MyConnection(stateChangedListeners).apply { setCallerDisplayName(name, TelecomManager.PRESENTATION_ALLOWED) setRinging() } return connection } そしお䞊蚘の発着信をしたずきに生成したConnectionに枡すlistenerの管理をするメ゜ッドを远加したす。 // class MyConnectionService companion object { // リスナヌが耇数セットされるため private val stateChangedListeners = mutableListOf<ConnectionStateChangedListener>() fun addConnectionStateChangedListener(listener: ConnectionStateChangedListener) { stateChangedListeners.add(listener) } fun removeConnectionStateChangedListener(listener: ConnectionStateChangedListener) { stateChangedListeners.remove(listener) } } Connection の実装 次に Connection を実装したす。 Connection はOSずアプリを繋ぐ重芁な圹割を持ったクラスです。 Connection を実装するにあたっおすべきこずは二぀あっお、䞀぀目はstateの倉化を取埗するこずです。䟋えばstateがIncomingになったら着信画面を衚瀺したり、stateがOutgoingになったら発信画面を衚瀺したり、stateに応じお行いたいこずがあるかず思いたす。そのためにstateの倉化を取埗したす。 二぀目は、OSに由来したポップアップに察しおナヌザヌがアクションしたずきに、OSからそのアクションを受け取るこずです。 Connection の onAnswer() , onDisconnect() などが呌ばれるので、その結果に応じお Connection のstateを倉曎したす。 これらを実装するこずによっお、OSにこのアプリの通話状態が䌝わったかどうかずいう情報や、他アプリの通話状態からどのような圱響を受けたか䟋えば他アプリで着信を受けたから受電するために、このアプリの通話は切電しようずした、などのアクション、などの情報を埗られたす。 具䜓的な実装に移りたす。 たずは Connection を継承し、初期化凊理を曞きたす。通話状態を監芖するためのlistenerのリストをコンストラクタに枡しおいたす。(耇数箇所で監芖する必芁がある堎合のためにlistenerを耇数セットできるようにリスト圢匏にしおいたす interface ConnectionStateChangedListener { fun onStateChanged(state: Int , connection: MyConnection) } class MyConnection( private val stateChangedListeners: MutableList <ConnectionStateChangedListener> = mutableListOf() ) : Connection() { init { audioModeIsVoip = true // 自己管理型の通話アプリの堎合は必芁です // これを蚭定しないず発信時にデフォルトの発信画面が衚瀺されたす connectionProperties = PROPERTY_SELF_MANAGED setInitializing() } 通話状態の倉曎があった堎合にlistenerに䌝えたす。 // class MyConnection override fun onStateChanged(state: Int ) { super .onStateChanged(state) stateChangedListeners.map { listener -> listener.onStateChanged(state, this ) } } たた、他のアプリずの通話状態の兌ね合いで、OS由来のポップアップが出おくるこずがあり、そのポップアップぞのアクション結果が䞋蚘の䞉぀のメ゜ッドにコヌルバックされたす。 たずは onDisconnect() に぀いおですが、䞀䟋ずしお、このアプリで通話䞭に他のアプリから発信しようずするず「この通話を発信するず、このアプリの通話が終了したす。」ずいう旚のポップアップが衚瀺され、OKをタップするず onDisconnect() がコヌルされたす。䞋蚘にサンプルずしおPixel5(Android 11)のポップアップを茉せたすが、OSや機皮によっお若干の文蚀の違いがあったり、挙動が異なる堎合がありたす。 ※「TelecomFrameworkSam...」ずいう衚瀺は、アプリ名であるTelecomFrameworkSampleが略されお衚瀺されたものです。 次に、 onAnswer() ず onReject() に぀いおです。䞀䟋ずしお、このアプリで着信䞭に他のアプリから着信があるず「応答するず、進行䞭の通話は終了したす」ずいうポップアップが出お、「応答」か「拒吊」かをタップするず䞊蚘メ゜ッドがコヌルされたす。䞋蚘がサンプルずなりたす。 ※「test incoming user」ずいうのは Connection に蚭定したもので、「Telecom..」ずいうのはアプリ名であるTelecomFrameworkSampleの略ずなりたす。 // class MyConnection override fun onAnswer() { super .onAnswer() // OS由来のポップアップに察しお電話に出るずいう類のアクションをするずコヌルされたす setActive() } override fun onReject() { super .onReject() // OS由来のポップアップに察しお拒吊するずいう類のアクションをするずコヌルされたす setDisconnected(DisconnectCause(DisconnectCause.REJECTED)) } override fun onDisconnect() { super .onDisconnect() // OS由来のポップアップに察しお切電するずいう類のアクションをするずコヌルされたす setDisconnected(DisconnectCause(DisconnectCause.UNKNOWN)) } Connectionの状態を倉曎・監芖する機胜の実装 前節においおConnectionの状態を取埗するずころたで実装できたした。 ただ、䞊述の䞀通りの実装を読んでみおも「結局のずころどのクラスをどうやっお䜿えば良いの」ずしっくりこないかず思いたす。より簡朔にテレコムフレヌムワヌクを扱えるようにしたいです。 冒頭の説明を繰り返すず、そもそもテレコムフレヌムワヌク本来の目的は「他の通話アプリず通話状態を共有するこず」でしたよね。 では、そのために必芁なこずは䜕なのか。 発信をOSに䌝えるこず 着信をOSに䌝えるこず 通話開始をOSに䌝えるこず 保留䞭をOSに䌝えるこず 通話終了をOSに䌝えるこず Connectionの状態通話状態を監芖するこず 䞊蚘を満たせば、OSに十分に通話状態が䌝わるかず思いたす。䞊蚘の箇条曞きをinterfaceにしおみたす。 interface TelecomHelper { @RequiresPermission (Manifest.permission.READ_PHONE_STATE) // 発着信の際に必芁なため fun initPhoneAccount(): PhoneAccount? @RequiresPermission (Manifest.permission.CALL_PHONE) fun startOutgoing(number: String , name: String , accountHandle: PhoneAccountHandle) fun startIncoming(name: String , accountHandle: PhoneAccountHandle) fun activate() fun hold() fun disconnect() fun firstConnectionOrNull(): MyConnection? fun addConnectionStateChangedListener(listener: ConnectionStateChangedListener) fun removeConnectionStateChangedListener(listener: ConnectionStateChangedListener) } ほずんど箇条曞きそのたたのinterfaceを定矩できたした。このinterfaceを実装しお必芁に応じお呌び出すこずができれば、アプリの゜ヌスコヌドがすごくクリヌンに保たれるかず思いたす。モゞュヌル化しおも良いず思いたす。 続いお、interfaceの実装サンプルです。やや実装量が倚いのでメ゜ッドごずに分解しお玹介しおいきたす。 たずクラスの構造に぀いおは、 TelecomHelper を継承しおコンストラクタにContextず TelecomManager をむンゞェクトし、 Connection を保持するリストをメンバに眮きたす。 class TelecomHelperImpl @Inject constructor ( @ApplicationContext private val context: Context, private val telecomManager: TelecomManager ) : TelecomHelper { private val connections = mutableListOf<MyConnection>() } 続いお各メ゜ッドに぀いおです。 たずは発着信時に、 ConnectionService においお生成されたConnectionをリストに远加したり、stateがdisconnectedになった時にリストから陀倖するためのlistenerをセットしたす。 // class TelecomHelperImpl init { // Connectionのaddやremoveをするためにリスナヌをセット val listener = object : ConnectionStateChangedListener { override fun onStateChanged( state: Int , connection: MyConnection ) { when (state) { Connection.STATE_RINGING -> { startConnection(connection) } Connection.STATE_DIALING -> { startConnection(connection) } Connection.STATE_DISCONNECTED -> { endConnection(connection) } } } } MyConnectionService.addConnectionStateChangedListener(listener) } listenerをadd or removeするためのメ゜ッドを远加したす。 // class TelecomHelperImpl override fun addConnectionStateChangedListener(listener: ConnectionStateChangedListener) { MyConnectionService.addConnectionStateChangedListener(listener) } override fun removeConnectionStateChangedListener(listener: ConnectionStateChangedListener) { MyConnectionService.removeConnectionStateChangedListener(listener) } Connection をメンバのリストにadd or removeするためのメ゜ッドです。 endConnection() においおは Connection の砎棄も行っおいたす。 // class TelecomHelperImpl private fun startConnection(connection: MyConnection) { connections.add(connection) } private fun endConnection(connection: MyConnection) { connections.remove(connection) connection.setDisconnected(DisconnectCause(DisconnectCause.UNKNOWN)) connection.destroy() } 次に、 PhoneAccount を取埗するためのメ゜ッドたちを実装したす。 PhoneAccount ずは、通話時の通信プロトコルの指定やself-managed圢匏の指定などをするためのクラスです。垞に新芏にアカりントを䜜るこずはせず、 ConnectionService に PhoneAccount が既に玐付いおいた堎合はそれを取埗したす。 // class TelecomHelperImpl @RequiresPermission (Manifest.permission.READ_PHONE_STATE) override fun initPhoneAccount(): PhoneAccount { return findExistingAccount(context) ?: return createAccount(context) } private fun createAccount(context: Context): PhoneAccount { val accountHandle = PhoneAccountHandle( ComponentName(context, MyConnectionService :: class .java), context.packageName ) val account = PhoneAccount.builder(accountHandle, "test" ) .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED) .setSupportedUriSchemes(listOf(PhoneAccount.SCHEME_SIP)) .build() telecomManager.registerPhoneAccount(account) return account } @RequiresPermission (Manifest.permission.READ_PHONE_STATE) private fun findExistingAccount(context: Context): PhoneAccount? { val connectionService = ComponentName( context, MyConnectionService :: class .java ) val targetPhoneAccountHandle = telecomManager.selfManagedPhoneAccounts.firstOrNull { phoneAccountHandle -> phoneAccountHandle.componentName == connectionService } return telecomManager.getPhoneAccount(targetPhoneAccountHandle) } 続いお、発信を開始するずきに startOutgoing() をコヌルしたす。その内郚で TelecomManager.placeCall() を呌びたす。これにより ConnectionService が立ち䞊がっお Connection が远加されたす。 // class TelecomHelperImpl @RequiresPermission (Manifest.permission.CALL_PHONE) override fun startOutgoing(number: String , name: String , accountHandle: PhoneAccountHandle) { telecomManager.placeCall( Uri.fromParts( "tel" , number, null ), Bundle().apply { putParcelable( TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, Bundle().apply { putString( "name" , name) } ) putParcelable( TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, accountHandle, ) } ) } そしお着信時に startIncoming() をコヌルしたす。その内郚で TelecomManager.addNewIncomingCall() を呌ぶこずで ConnectionService が立ち䞊がっお、 Connection が远加されたす。 // class TelecomHelperImpl override fun startIncoming(name: String , accountHandle: PhoneAccountHandle) { telecomManager.addNewIncomingCall( accountHandle, Bundle().apply { putParcelable( TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, Bundle().apply { putString( "name" , name) } ) } ) } そしお最埌に、通話状態が倉曎された際に、そのこずをアプリからOSに䌝えるために Connection むンスタンスのstateを倉曎したす。 activete() メ゜ッドは、通話開始時および保留解陀時、 hold() メ゜ッドは、保留開始時、 disconnect() メ゜ッドは切電時にコヌルするようにしたす。 実装䟋は以䞋の通りです。 // class TelecomHelperImpl override fun activate() { connections.lastOrNull { it.state == Connection.STATE_DIALING || it.state == Connection.STATE_RINGING || it.state == Connection.STATE_HOLDING }?.setActive() } override fun hold() { connections.lastOrNull { it.state == Connection.STATE_ACTIVE }?.setOnHold() } override fun disconnect() { connections.lastOrNull { it.state == Connection.STATE_DIALING || it.state == Connection.STATE_RINGING || it.state == Connection.STATE_ACTIVE || it.state == Connection.STATE_HOLDING }?.let { endConnection(it) } } 以䞊がTelecomHelperの実装䟋ずなりたす。 Connection の状態通話状態の監芖 前節の序盀で、 Connection のstateを監芖するためのメ゜ッドを远加したした。 // class TelecomHelperImpl override fun addConnectionStateChangedListener(listener: ConnectionStateChangedListener) { MyConnectionService.addConnectionStateChangedListener(listener) } override fun removeConnectionStateChangedListener(listener: ConnectionStateChangedListener) { MyConnectionService.removeConnectionStateChangedListener(listener) } 䞊蚘の二぀のメ゜ッドです。 本節では、このlistenerのセット方法ず、監芖方法に぀いおの実装サンプルをご玹介したす。 // class SomeViewModel: ViewModel() private val listener = object : ConnectionStateChangedListener { override fun onStateChanged( state: Int , connection: MyConnection ) { STATE_INITIALIZING -> {} STATE_NEW -> {} STATE_RINGING -> {} STATE_DIALING -> {} STATE_ACTIVE -> {} STATE_HOLDING -> {} STATE_DISCONNECTED -> {} STATE_PULLING_CALL -> {} } } init { telecomHelper.addConnectionStateChangedListener(listener) } override fun onCleared() { // メモリリヌクしないように telecomHelper.removeConnectionStateChangedListener(listener) super .onCleared() } 䞊蚘で Connection のstateの倉化を監芖できたす(メモリリヌクしないよう、ラむフサむクルに応じお適切にlistenerを取り倖しおください)。 これによっお、䟋えば発信がスタヌトしたずきに STATE_DIALING の郚分を通るので発信画面を出したり、着信なら STATE_RINGING を通るので着信画面を出したり、 STATE_DISCONNECTED なら通話䞭画面を閉じたりずいった実装ができたす。 以䞊で実装方法に぀いおは終わりたす。Helperクラスを介しお、アプリずOS間で通話状態の共有ができたした。 終わりに テレコムフレヌムワヌクの導入に関する情報はニッチすぎおなかなか芋぀からないので、今埌実装に取り組たれる方にずっおこの蚘事が少しでもお圹に立おれば幞いです。 たた、RevComm でぱンゞニアを募集しおいたす。技術奜きな方々が倚く圚籍しおおり、モブプロや勉匷䌚などが盛んに行われおいたす。ぜひぜひ奮っおご応募ください。 www.revcomm.co.jp 参考 公匏ドキュメント: Telecom フレヌムワヌクの抂芁 linphone-android
こんにちは RevComm に2022幎1月に入瀟したフロント゚ンド゚ンゞニアの小山 (koji-koji) です。 RevComm では、 React を採甚しおいるサヌビスの状態管理に Recoil を䜿っおいたす。今回は Recoil の理解をより深めるために Context ず比范しおみたした。 Context では小さく状態管理できる。 Recoil でもできないか Context の状態管理のスコヌプは <Context.Provider> で括った察象であり、䞀方 Recoil では <RecoilRoot> で括った察象です。 Context では、ルヌトコンポヌネント以倖を <Context.Provider> で括った堎合、子コンポヌネントでの倉曎はグロヌバルには反映されたせん。 ロヌカルではないけれど、グロヌバルずいうほど倧きくなく状態管理をしたいずきに䜿えたす。それが Recoil でもできるのかず考えたした。 Recoil では atomFamily() を䜿っお atom の key を動的に生成する方法があるようです。これはリストを扱うずきは良さそうです。䞀方、リストでない堎合もあるので、もう少し調べおみたした。 <RecoilRoot> をネストさせるず小さく状態管理できる <RecoilRoot> のドキュメント によるず、ネストさせるずスコヌプを調敎できるこずがわかりたした。 ルヌトコンポヌネントだけでなく子コンポヌネントでも䜿うず、子コンポヌネントの䞭だけで状態管理ができたす。 芪コンポヌネントで状態を倉曎しおも、子コンポヌネントには反映されたせん。 子コンポヌネントで状態を倉曎しおも、芪コンポヌネントには反映されないずいう圢でスコヌプが狭たりたす。 サンプルです。 サンプルコヌド function MyApp ( { Component , pageProps } : AppProps ) { return ( < RecoilRoot > < Component { ...pageProps } id = "modalId" / > < /RecoilRoot > ); } const ParentComponent: React.FC = () => { const [ sample , setSample ] = useRecoilState ( sampleState ); return ( < div className = "bg-blue-100 p-2" > ParentComponent: { sample } < button className = "ml-3 bg-gray-100 p-3" onClick = { () => setSample ( sample + 1 ) } > ボタン < /button > < div className = "mt-2 flex" > < RecoilRoot > < NestChildComponentA / > < NestChildComponentB / > < /RecoilRoot > < ChildComponentC / > < /div > < /div > ); } ; const NestChildComponentA: React.FC = () => { const [ sample , setSample ] = useRecoilState ( sampleState ); return ( < div className = "bg-pink-300 p-2" > < RecoilRoot > NestChildComponentA: { sample } < button className = "ml-3 bg-gray-100 p-3" onClick = { () => setSample ( sample + 1 ) } > ボタン < /button > < NestGrandChildComponent / > < /RecoilRoot > < /div > ); } ; const NestChildComponentB: React.FC = () => { const [ sample , setSample ] = useRecoilState ( sampleState ); return ( < div className = "bg-green-300 p-2" > < RecoilRoot > NestChildComponentB: { sample } < button className = "ml-3 bg-gray-100 p-3" onClick = { () => setSample ( sample + 1 ) } > ボタン < /button > < /RecoilRoot > < /div > ); } ; const ChildComponentC: React.FC = () => { const [ sample , setSample ] = useRecoilState ( sampleState ); return ( < div className = "bg-yellow-300 p-2" > < RecoilRoot > ChildComponentB: { sample } < button className = "ml-3 bg-gray-100 p-3" onClick = { () => setSample ( sample + 1 ) } > ボタン < /button > < /RecoilRoot > < /div > ); } ; const NestGrandChildComponent: React.FC = () => { const [ sample , setSample ] = useRecoilState ( sampleState ); return ( < div className = "mt-2 bg-blue-300 p-2" > < RecoilRoot > NestGrandChildComponent: { sample } < button className = "ml-3 bg-gray-100 p-3" onClick = { () => setSample ( sample + 1 ) } > ボタン < /button > < /RecoilRoot > < /div > ); } ; export const sampleState = atom < number >( { key: 'SampleAtom' , default : 0 , } ); </div> <RecoilRoot> を適切にネストさせるこずで状態管理のスコヌプを調敎できそうですね。 なぜ <RecoilRoot> をネストさせるずスコヌプが閉じるのか <RecoilRoot> をネストさせたずきの挙動はわかったのですが、なぜこうなるのかあたりよくわかりたせんでした。 そこで RecoilRoot のコヌド を芋おみたした。 Flow で曞かれおいたすが、あたり知識がなくおも読めそうです。 553 行目から RecoilRoot の蚘述がありたす(今回参照した Recoil のバヌゞョンは 0.7.2 です)。 function RecoilRoot ( props: Props ) : React. Node { const { override , ...propsExceptOverride } = props ; const ancestorStoreRef = useStoreRef (); if ( override === false && ancestorStoreRef.current !== defaultStore ) { // If ancestorStoreRef.current !== defaultStore, it means that this // RecoilRoot is not nested within another. return props.children ; } return < RecoilRoot_INTERNAL { ...propsExceptOverride } / >; } ストアを比范しお異なっおいる堎合はネストしおいるので、凊理を分けおいるずいう感じです。 ネストしおいる堎合は、別のストアを䜜るずいう凊理をしおいたす。 なお Recoil_RecoilRoot.js の䞭のコヌドで気が぀いたのですが、 useContext を䜿っおいたした。 私は Recoil を觊る前は、 Context vs Recoil ずいうむメヌゞを持っおいたした。しかしその理解は少し違っおいたみたいです。 Recoil は Context を内郚的に䜿っおいお、 atom ず selector をうたく掻甚するこずで再レンダリングを抑えおいるずいった方が正しそうです。 RecoilRoot の挙動に぀いおの蚘事は以䞊です。 今回はドキュメントを読むのに加えお、実際に挙動を確認したり、コヌドリヌディングをしたした。 コヌドリヌディングをするず、やはり理解が深たったり発芋があったりしたすね 今埌も気になるずころがあったら、どんどんコヌドリヌディングしおいきたいです。
RevComm で Software Engineer をやっおおりたす、䜐藀ず申したす。 珟時点で匊瀟には4名の䜐藀が圚籍しおいたすが、今のずころ党員の所属郚門が倧きく違うため、苗字で呌ばれおもあたり困らない日々を過ごしおおりたす。 今回は匊瀟で利甚しおいる E2E テストツヌルの Autify に぀いおのお話です。実際の運甚に぀いお少しだけ螏み蟌んだ話になりたすので、Autify に぀いおの玹介・説明は省いおいる堎合がありたす。Autify を利甚しおいる・利甚を怜蚎しおいる方に読んでいただけたら嬉しいです。 最初の実行回数オヌバヌが契機に ある月の半ばに「このたたいくず Autify の実行回数が圓初賌入分を超えるかも」ずいう状況が発生したした。これは匊瀟の補品 MiiTel の E2E テストツヌルずしお Autify を導入しおから初めおのこずです。 その時点で、完成圢のシナリオ数ず珟圚回しおいる定期実行のペヌスを元に月圓たりの実行ペヌスを算出したずころ、今のプランでは明らかに実行回数が足りないこずが刀明したした。 そこで Autify の利甚方針を定めお最適な実行回数を芋積もり、それを持っお Autify 瀟ず実行回数を増やす盞談をしよう、ずいうこずになりたした。 導入初期を思い出すず、実行回数は今のプランで足りるのかずいうこずを怜蚎できるくらいシナリオが出揃った事はかなり感慚深いものがありたす。 必芁な消費回数の芋積もり MiiTel にはさたざたなマむクロサヌビス(以䞋サヌビス)が存圚し、それぞれの実装を行うチヌムが Autify のシナリオ実装も行っおいたす。たた、SLA や障害時のリスクずいった必芁な実行回数の根拠ずなる考え方も、サヌビスによっお異なりたす。 䞀方、Autify の実行回数は䌚瀟単䜍の数字です。䜕の制限もなく䜿っおいった結果、あちらのチヌムが䜿いすぎお別のチヌムが困った...ずいう事態は防ぎたいずころです。 最終的には、以䞋のような䜓系で指針を瀺し、それに沿っお各チヌムが芋積もった数字を合算しお党䜓の消費回数芋積ずするこずにしたした。 補品をテストするための実行 自サヌビスリリヌス時の実行 リリヌス前にステヌゞング環境で実行 リリヌス埌にプロダクション環境で実行 他サヌビスの倉曎に圱響を受けるシナリオの実行 MiiTel 以倖のサヌビスに圱響を受けるシナリオの実行 MiiTel の他サヌビスの倉曎に圱響を受けるシナリオの実行 それ以倖の実行 シナリオ実装時の実行 シナリオメンテナンス時の実行 補品をテストするための実行 数字を芋積もる䞊では、シナリオ実行を「補品をテストするための実行」ず「それ以倖の実行」に分ける必芁がありたす。 「補品をテストするための実行」はMiiTel の E2E テストずしお実行するこずです。普通に考えたらここに぀いおだけ数字を考えれば良さそうな気がしおしたいたす。 䞀方、「それ以倖の実行」ずは、シナリオを䜜成する際に詊しに回す実行や、Autify の運甚䞭にテストがコケおしたいメンテナンスする時の実行などです。ここを極力枛らす方法も考えがちですが、人間が手を動かす時間を削枛したくお導入した Autify の実行回数を枛らすために人手を割くようになるず本末転倒ですから、倧たかにでもこの数字を芋積もっおおく必芁がありたす。 自サヌビスリリヌス時の実行 自分のチヌムが担圓するサヌビスに察するテストは、リリヌス時だけ行えば良さそうです。リリヌス前に䞍具合をキャッチできるよう、ステヌゞング環境で網矅的な回垰テストを実行。たた、プロダクションでも同じ内容でもう䞀床実行したす。同じテストを二床実斜するのは、環境差異が動䜜に圱響する可胜性を朰したい、お客様に䜿っおいただいおいる環境でテストが終わっおいれば安心ずいう理由です。 ぀たり、シナリオ数の芋積もりは以䞋のようになりたす。 フルテストのシナリオ数 × 月圓たりのリリヌス回数 × 2 他サヌビスの倉曎に圱響を受けるシナリオの実行 MiiTel のサヌビスの䞭には、リリヌス時に他のサヌビスの倉曎に圱響を䞎えおしたうものがありたす。他のチヌムのサヌビスのテストを行うこずを考える堎合、それに䌎うリスクやコストも考える必芁がありたす。そこで、MiiTel 内の他サヌビス・他瀟のサヌビスに倉曎があった際に圱響を受ける箇所のテストを毎日定期実行で回す方針にしたした。リリヌスを行う圱響を䞎える偎のチヌムではなく、圱響を受ける偎がテストに぀いお責任を持おる圢になりたす。 シナリオ数の芋積もりは以䞋のようになりたす。 圱響を受けるテストのシナリオ数 × 31 たた、MiiTel 内のサヌビスであればリリヌスが行われる可胜性が䜎い曜日が決たっおいたすから、MiiTel 内の他サヌビスに圱響を受けるテストの堎合は以䞋のようになりたす。 圱響を受けるテストのシナリオ数 × 20 それ以倖の実行 すでに説明した、補品をテストするための実行以倖のテストです。こちらは実瞟から芋積もるしかありたせん。珟時点ではそういった画面は甚意されおいないため、テスト結果怜玢画面で YYYY-MM察象の幎月を怜玢しおその月を怜玢しお件数を確認したした。今回調べたずころでは、党䜓の実行回数に察し玄30%が「それ以倖の実行」によるものでした。 シナリオ䜜成䜜業のボリュヌムは䜜成枈みのシナリオ数には関係がないため厳密ではありたせんが、いったんこの方法でずりあえずの最倧倀は決めるこずにしたした。 今埌の課題 以䞊の方法で、匊瀟では Autify の実行回数を倧たかに芋積もるこずができたした。他瀟で Autify を導入する際にそのたた䜿えるやり方ではないかもしれたせんが、同じ考え方で適切な実行数を保おるず思いたす。 ずはいえ、ただただ課題はたくさんありたす。珟圚は、Autify のシナリオレビュヌをどう管理しおいこうかずいう課題に取り組んでいたす。今埌埐々に手動テストを削っおいくにあたっお、自動テストが適切に䜜成されおいるこずを担保したいからです。 RevComm は高い安定性を求められるプロダクトにおける E2E テストの実装や運甚に興味のある゚ンゞニアを募集しおおりたす。ご興味ある方のご応募、お埅ちしおおりたす。 hrmos.co
こんにちは。 Infrastructure (むンフラチヌム) 所属の小門です。 RevComm (レブコム) では、電話営業や顧客察応を可芖化する音声解析 AI 搭茉型のクラりド IP 電話 MiiTel (ミヌテル) を提䟛しおいたす。 miitel.com はじめに MiiTel を含め RevComm ではクラりドプラットフォヌムに AWS を利甚しおいたす。 環境や甚途に応じお耇数の AWS アカりントを保有しおいたす。 各 AWS アカりントの特暩ID (※) を䜿甚できるのは、業務䞊必芁ずするごく少数のメンバヌのみに制限しおおり、必芁が生じたメンバヌには䞀時的に暩限付䞎する運甚をしおいたす。 ※特暩ID ルヌトナヌザヌや AdministratorAccess IAMポリシヌがアタッチされたナヌザヌID (= Admin ロヌル) 特暩IDをやみくもに䜿甚するこずはセキュリティガバナンス面でリスクが高いため、原則必芁十分な暩限を持぀ナヌザヌIDで操䜜するルヌルずしおいたす。 䟋えば、環境の確認をする堎合には ReadOnlyAccess、リリヌス䜜業をする堎合には PowerUserAccess を䜿甚するずいうむメヌゞです。 今回は、やみくもな特暩IDの䜿甚に察するけん制やアカりント流出のリスクに備えるために特暩IDの䜿甚を怜知する仕組みを構築したした。 たた特暩ID䜿甚時には甚途や䜜業内容を蚘茉する運甚ルヌルずし、監査蚌跡ずしお残せるようにしおいたす。 党䜓構成 ステップ1. ログむン怜知 (メヌル通知) ルヌトナヌザヌ Admin ロヌル 通知結果 ステップ2. 個別メンション付きリプラむ Slack App 䜜成 メンション甚のナヌザヌID取埗 ボットのコア凊理 デプロむ 動䜜確認 たずめ 党䜓構成 ステップ1. ログむン怜知 (メヌル通知) ステップ2. 個別メンション付きリプラむ 倧きく2段階に構成になっおいたす。 ステップ1. ログむン怜知 (メヌル通知) ルヌトナヌザヌ AWS ルヌトナヌザヌがログむンしたこずを通知するための CloudFormation (以䞋、CFn) テンプレヌトが公開されおおり、これを参考にしたした。 CloudTrail を介しおルヌトナヌザヌのログむンを怜知し EventBridge、SNS 経由でメヌルが送信されたす。 参考: ルヌトナヌザヌアカりントが䜿甚されたこずを通知する EventBridge むベントルヌルを䜜成する ルヌトナヌザヌがログむンした CloudTrail むベントレコヌドは䞋蚘のようになり、これが䞊蚘 CFn テンプレヌトの EventPattern に察応しおいたす。たた IAM はグロヌバルリヌゞョンサヌビスのため CloudTrail むベントデヌタが us-east-1 リヌゞョンに集玄される点に泚意したす。 CloudTrail むベントレコヌド (抜粋) { " eventVersion ": " 1.08 ", " userIdentity ": { " type ": " Root ", ... } , " awsRegion ": " us-east-1 ", " eventType ": " AwsConsoleSignIn ", ... } CFn テンプレヌト (抜粋) Resources : ... EventsRule : Type : AWS::Events::Rule Properties : Description : Events rule for monitoring root AWS Console Sign In activity EventPattern : detail-type : - AWS Console Sign In via CloudTrail detail : userIdentity : type : - Root ... Admin ロヌル 䞊蚘を参考にしお特定の IAM ロヌルが䜿甚されたこずを怜知するむベントパタヌンも䜜成したした。 RevComm では、Google Workspace を甚いた AWS SSO によっお開発者が IAM ロヌルを䜿甚するルヌルになっおいたす。 Google アカりント認蚌埌に IAM ロヌルを利甚するず、裏偎で AssumeRoleWithSAML ずいうアクションが実行され CloudTrail で怜知できたす。 コン゜ヌルログむン AWS CLI などによる認蚌情報取埗 ( aws sts assume-role-with-saml ... ) の䞡操䜜をカバヌできたす。 CloudTrail むベントレコヌド(抜粋) { " eventVersion ": " 1.08 ", " userIdentity ": { " type ": " SAMLUser ", " userName ": " xxx@revcomm.co.jp ", ... } , " eventSource ": " sts.amazonaws.com ", " eventName ": " AssumeRoleWithSAML ", " awsRegion ": " us-east-1 ", " requestParameters ": { ... " roleArn ": " arn:aws:iam::012345678910:role/AdministratorRole ", ... } , ... } CFn テンプレヌト(抜粋) Mappings : AccountAdminRoleNameMapping : AdminRoleArn : # account-1 "012345678910" : arn:aws:iam::012345678910:role/AdministratorRole # ... Resources : ... AssumeRoleWithSAMLEventsRule : Type : AWS::Events::Rule Properties : EventPattern : detail-type : - "AWS API Call via CloudTrail" detail : eventSource : - "sts.amazonaws.com" eventName : - AssumeRoleWithSAML requestParameters : roleArn : - !FindInMap [ AccountAdminRoleNameMapping, AdminRoleArn, !Ref "AWS::AccountId" ] ... 通知結果 正しく蚭定できるず、䞋蚘のようにメヌル送信するこずが確認できたす (Slack) 。 たた、EventBridge の「入力トランスフォヌマヌ」を䜿甚しお各皮情報を抜粋しおいたす。 ルヌトナヌザヌのログむン通知 Admin ロヌルのログむン通知 ステップ2. 個別メンション付きリプラむ ログむン怜知から通知たでの仕組みができたしたが、䞀歩螏み蟌んで個別メンションするようにしたした。 ステップ1 で Slack に送信されたメヌルをトリガヌにした Slack App (ボット) を䜜成し、AWS Lambda で動䜜させおいたす。 ボットの実装には Slack が公匏に公開しおいるフレヌムワヌクである Bolt for Python を䜿甚したした。 slackapi/bolt-python: A framework to build Slack apps using Python ドキュメント: Slack | Bolt for Python Lambda ランタむムは Python 3.9、ラむブラリは䞋蚘のバヌゞョンを䜿甚しおいたす。 slack-bolt==1.11.2 slack-sdk==3.13.0 Slack App 䜜成 Slack App コン゜ヌル から「Create New App」を遞び、新芏アプリを䜜成したす。 Slack App がメッセヌゞの受信をハンドルできるよう「Event Subscriptions」をオプトむンしたす。※Slack App 自䜓の詳现な手順は本蚘事では割愛させお頂きたす。 Lambda 関数で利甚するトヌクン情報の取埗方法のみ蚘茉したす。 SLACK_BOT_TOKEN OAuth & Permissions > OAuth Tokens for Your Workspace > Bot User OAuth Token SLACK_BOT_SIGNING_SECRET Settings > App Credentials > Signing Secret メンション甚のナヌザヌID取埗 ボットから送信するメッセヌゞでメンションを付けるには単に @xxx ずするのではなく、 <@[user-id]> ずする必芁がありたす。 [user-id] は Slack 内郚で管理されおいる固有倀です( "W012A3CDE" のような圢匏)。 個別メンションのためにナヌザヌIDをメヌルアドレスから取埗する必芁がありたす。 from typing import Optional from slack_sdk import WebClient SLACK_BOT_TOKEN = 'xxx' def get_user_id_by_email_address (email_address: str ) -> Optional[ str ]: client = WebClient(token=SLACK_BOT_TOKEN) response = client.users_lookupByEmail(email=email_address) if not response.data.get[ "ok" ]: return if response.data.get( "error" ) == "users_not_found" : return return response.data[ "user" ][ "id" ] 参考: users.lookupByEmail method | Slack ボットのコア凊理 Bolt App を初期化するず @app.event のようにデコレヌタヌで Slack 䞊のむベントをリッスンしお凊理を実装できたす。 たた゚ントリヌポむントずなる lambda_handler もフレヌムワヌクのメ゜ッドが甚意されおいるため簡朔に実装するこずができたす。 import json import re from typing import Union from slack_bolt import App from slack_bolt.adapter.aws_lambda import SlackRequestHandler from slack_sdk import WebClient SLACK_BOT_TOKEN = 'xxx' SLACK_BOT_SIGNING_SECRET = 'xxx' app = App( process_before_response= True , token=SLACK_BOT_TOKEN, signing_secret=SLACK_BOT_SIGNING_SECRET ) @ app.event ({ "type" : "message" , "subtype" : "file_share" , }) def reply_to_sns_email (body, logger): """Amazon SNS からのメヌル通知に察しおメンション付きスレッド返信を行う""" attachment = body[ "event" ][ "files" ][ 0 ] # メヌル以倖のむベントはスキップする if attachment[ "filetype" ] != "email" : return { 'statusCode' : '200' , 'body' : json.dumps({ 'message' : 'This message is not email.' }) } # ... email_body = attachment[ "plain_text" ] # " -- " 以降の改行を含む党おの文字を陀去する login_info_text = re.sub( "--.*" , "" , email_body, flags=re.DOTALL).replace( " \r\n " , "" ) login_info = json.loads(login_info_text) arn = login_info[ "RoleArn" ] if arn.endswith( "root" ): """root ナヌザヌが䜿甚された堎合 e.g. arn:aws:iam::012345678910:root """ user_id = None message_abstract = "rootナヌザヌによるコン゜ヌルログむンが行われたした。" else : """Assumed Role Arn からログむン者のメヌルアドレスを取埗する""" email_address = login_info[ "UserName" ] message_abstract = "暩限の匷いアカりントが䜿甚されたした。" # メヌルアドレスから Slack ナヌザID を玐づける user_id = get_user_id_by_email_address(email_address) if user_id is None : mention = "<!here>" else : mention = f "<@{user_id}>" message_text = \ mention + " \n " + message_abstract + " \n " \ "- 䜜業目的や内容 \n " \ "- タスクチケットURL \n " \ "などを蚘入しおください。" client.chat_postMessage( channel=body[ "event" ][ "channel" ], thread_ts=body[ "event" ][ "event_ts" ], text=message_text ) return { 'statusCode' : '200' , 'body' : json.dumps({ 'message' : 'ok' }) } def lambda_handler (event, context): slack_handler = SlackRequestHandler(app=app) return slack_handler.handle(event, context) デプロむ 䞊蚘の Lambda 関数をデプロむし、API Gateway の配䞋に配眮したす。 API Gateway は「REST API」ではなく「HTTP API」で䜜成する必芁があるので泚意したす。 デプロむ埌、API Gateway の URL を Slack App のリク゚スト URL に登録したす。 ※Features > Event Subscriptions > Request URL 動䜜確認 ここたでの手順が正しく蚭定できおいれば、ルヌトナヌザヌ/Admin ロヌルのログむンを契機に䞀連凊理を通しおボットによる個別メンション付きリプラむが届きたす。 たずめ 特暩IDの䜿甚を通知し、セキュリティガバナンスを改善する取り組みに぀いおご玹介したした。 本蚘事の取り組みでは䞋蚘のメリットを実珟したした。 特暩IDがやみくもに䜿甚されるこずをけん制し぀぀、䜿甚状況をモニタリングする 特暩IDを甚いる䜜業内容の監査蚌跡を残す RevComm ではお客様に安心しお補品をご利甚頂けるよう、匕き続きセキュリティの向䞊に力を入れおたいりたす。 Infrastructure では、プロダクト暪断で考慮するセキュリティの管理や IaC 、たた䞀郚オンプレ環境の管理・運甚を行っおいたす。ご尜力頂ける゚ンゞニアを探しおいたす。 むンフラ以倖にも党方䜍で゚ンゞニアを積極的に採甚䞭ですのでぜひ採甚サむトをご芧ください www.revcomm.co.jp
こんにちは、RevComm の玉城です。MiiTel Analytics のサヌバヌサむドの開発を䞻に担圓しおいたす。MiiTel Analytics は通話や䌚議の履歎・音声解析結果を集玄し可芖化する補品です。 MiiTel Analytics では以䞋の2぀を提䟛するために Amazon OpenSearch を運甚しおいたす。 党文怜玢機胜 䜿甚単語頻床レポヌト この Amazon OpenSearch のシャヌド数を切り替えるタむミングがありそちらを私が担圓したしたので、その時の内容を玹介したいず思いたす。 シャヌド数切り替えに至った経緯 リむンデックスずは リむンデックスの高速化 MiiTel における OpenSearch ぞのデヌタ登録の仕組み たずめ シャヌド数切り替えに至った経緯 OpenSearch には MiiTel Analytics で解析された応察履歎が保存されたす。そのため、MiiTel の利甚ナヌザヌが増えるず保存されるデヌタも増倧し、曞き蟌み/怜玢に掛かる負荷が倧きくなっおいきたす。参考ずしお、蚘事執筆時点では 1 億近いドキュメント数ず 300 GB を超えるデヌタサむズずなっおいたす。 このようにデヌタ数増倧による負荷増倧ぞの察応ずしお、OpenSearch にはむンデックス毎にシャヌド数を蚭定したす。シャヌドずは、OpenSearch でクラスタヌにデヌタを分散するずきの単䜍です。 切り替え前のシャヌド数は 2 で各シャヌド数の容量は玄 65 GB でした。AWS 偎では適切なシャヌドのサむズは 10 〜 50 GiB にするこずを掚奚しおおり、既に掚奚倀を超えおいる状態でしたので早めの察応が必芁でした。 そのため、今回の察応ではシャヌド数を 2 -> 4 に増やしおデヌタを分散させるこずで各シャヌド毎のサむズを 10 〜 50 GiB 以内に収めたした。 参考: Amazon OpenSearch Service ドメむンのサむゞング - Amazon OpenSearch Service リむンデックスずは OpenSearch のシャヌド数蚭定はむンデックス䜜成の際に行われたす。既存のむンデックスのシャヌド数を途䞭で倉曎するこずはできたせん。そのため、今回のシャヌド数切り替えのためにリむンデックスを行いたした。 リむンデックスずは既存むンデックスずは別に新しくむンデックスを䜜成し、既存むンデックスのデヌタをたるたる新しいむンデックスにコピヌするこずです。この新しくむンデックスを䜜成する際に、シャヌド数を 4 に蚭定するこずでシャヌド数切り替えの察応を行いたす。 新むンデックスを䜜成したす。その際に既存むンデックスから曎新したい蚭定倀を新たに蚭定したす。今回の堎合はシャヌド数です。 既存むンデックスから新むンデックスに向けお Reindex API を実行したす。 既存むンデックスから新むンデックスぞ゚むリアスを倉曎し既存むンデックスを削陀したす。 リむンデックスの高速化 リむンデックスを行う䞊で泚意したい蚭定がありたす。それは refresh_interval です。refresh_interval はむンデックスのドキュメント曎新を怜玢に反映する操䜜の実行間隔になりたす。refresh_interval が 10 秒だった堎合、䞋蚘の図のようにむンタヌバルの間に起こった倉曎は次のむンタヌバルにお怜玢ができるようになりたす。 refresh_interval の蚭定を無効にするこずでリむンデックスの実行時間を早く終わらせるこずができたす。詳现は埌述したすが、今回のリむンデックス䜜業䞭はデヌタの曎新を䞀時的に止めるこずで、新しくデヌタが投入されない状況にするこずができたした。そのため、refresh_interval の蚭定を無効にするこずができたした。 䟋ずしお玄 110 䞇のドキュメント数に察しお refresh_interval を -1無効ず 100 秒で比范怜蚌したずころ、-1 の堎合は 5 分 50 秒だったのに察しお 100 秒の堎合は 11 分 19 秒ず倍近くの差が出たした。 MiiTel における OpenSearch ぞのデヌタ登録の仕組み MiiTel Analytics で解析された応察履歎は Amazon RDS ぞ保存されたす。OpenSearch ぞはこの Amazon RDS ぞデヌタが保存されたタむミングでデヌタが同期されたす。 応察履歎を RDS ぞ保存/曎新 保存/曎新された応察履歎 ID を SQS に送信 Lambda が応察履歎 ID を SQS より取埗 Lambda にお応察履歎を OpenSearch ぞ同期する API を呌び出す 同期 API のリク゚ストの応察履歎 ID を元に RDS より応察履歎を取埗 取埗した応察履歎を OpenSearch 甚に倉換し登録 今回のリむンデックス䜜業では䞊図の定期実行される Lambda を䞀時的に止めたす。それによりリむンデックス䞭は䞊図の 3 〜 6 が止たり、OpenSearch ぞのデヌタ远加/曎新が行われないのでデヌタの䞍敎合を防ぐこずができたす。 たた、䞊図の 1 〜 2 はリむンデックス䞭も皌働しおいるので SQS には新芏たたは曎新された応察履歎の ID が溜たっおいきたす。これらの応察履歎はリむンデックスが完了した埌に Lambda を再皌働するこずで OpenSearch ぞ登録されたすので、リむンデックス䞭の応察履歎も取り零すこずなくシャヌド数の切り替えが行えたす。デメリットは䞀点で、デヌタ同期を䞀時的に止めるのでリむンデックス䞭は最新のデヌタを扱えなくなりたす。 *1 䞊蚘で説明しおきたように、今回のリむンデックスはサヌビスのダりンタむムなしで行えたす。しかしながら最新のデヌタを扱えないたたサヌビスを提䟛するのはあたり宜しくないため、顧客に事前にメンテナンス時間を通知し、その時間内にシャヌド数の切り替えを行いたした。 デヌタ数が倚いのでリむンデックスが完了するたでに玄 8 時間も掛かりたした。お客様にご協力いただいたおかげで refresh_interval を無効にするこずができたのでこの時間で収たったこずになりたす。もしも refresh_interval を 100 秒に蚭定しおいたら倍の 16 時間は掛かっおいたかず思うず恐ろしいです。 たずめ 今回のシステム芁件ずデヌタ量の堎合、ダりンタむムなしの玄 8 時間でリむンデックスが完了したした。しかし、近い将来にたた負荷を緩和するためのシャヌド数の切り替えを行わなければなりたせん。なぜなら、このリむンデックスを行った圓時のドキュメント数は玄 6,600 䞇で珟圚は玄 9,300 䞇匱ずありがたいこずに利甚者は順調に増えおいるからです。 今回の察応が次回も䞞々䜿えるかず蚀うず芏暡が増倧しおいるため䜿えないず思いたす。しかし、今回の察応でシャヌド数切り替えやリむンデックスに察する知芋は埗られたので、今埌の Amazon OpenSearch の運甚をより良くしおいくために暡玢しおいきたいず思いたす。 リむンデックスは、リむンデックス䞭のデヌタ登録/曎新/怜玢が行なえたす。しかし、リむンデックス䞭のコピヌ元のデヌタ登録/曎新はコピヌ先ぞ反映されないため、コピヌ元ずコピヌ先のむンデックス内容に差異が生じたす。 *1 : リむンデックスは、リむンデックス䞭のデヌタ登録/曎新/怜玢が行なえたす。しかし、リむンデックス䞭のコピヌ元のデヌタ登録/曎新はコピヌ先ぞ反映されないため、コピヌ元ずコピヌ先のむンデックス内容に差異が生じたす。