セーフィー株式会社のブログ - TECH PLAY

TECH PLAY

セーフィー株式会社

セーフィー株式会社 の技術ブログ

269

こちらは Safie Engineers' Blog! Advent Calendar の18日目の記事です。 こんにちは。セーフィー株式会社でバックエンドエンジニアをしている河津です。 私たちの会社は2023年10月27-28日に、PyCon APAC 2023への出展を行いました。この記事では、出展までの準備や当日の様子について紹介したいと思います! PyConとは 用意したデザインアイテム 当日の様子 出展デモ Safie One Safie Pocket2 Plus Safie Connect 撤収と振り返り PyConとは プログラミング言語「Python」を中心としたボランティアによる非営利の年次カンファレンスです。 セーフィーは前回開催された PyCon JP 2022 から出展していますが、2023年はなんと10年ぶりの国際カンファレンスとなる PyCon APAC 2023 が日本で開催されることになりました。 2023-apac.pycon.jp PyCon APACの運営チームは、アジア太平洋地域における国または地域が主体となり、現在では、シンガポール、マレーシア、インドネシア、フィリピン、タイ、韓国、香港、ベトナム、日本、台湾、インド、バングラデシュが毎年交代して開催されるそうです。 世界中のPythonエンジニアにセーフィーの存在を認知いただくチャンス!ということで出展準備を進めていきました。 用意したデザインアイテム 前回出展時の反省点の一つに、ブースに来ていただいた方々に会社のことを知っていただくためにお見せする資料などの用意が不十分だったというものがありました。 商品説明などは販促用パンフレットなどを使うことができますが、来場するエンジニアの方々が興味ありそうなシステム構成や技術スタック、どのあたりにPythonが使われているの?などの技術的な質問に対して、口頭でしか回答できないというもどかしさがありました。 そのため今回は、システム構成や技術スタックなどを説明するためのA1サイズのパネルやパンフレットを準備しました。見やすい内容となるようにデザイナーの方々にデザインいただきました。 A1パネル パンフレット めちゃくちゃ素敵なデザインとなりました!このパネルとポスターがあればセーフィーすごいと思ってもらえるはず。 今回は国際カンファレンスなので海外のエンジニアの方々も多く来場すると予想し、英語バージョンのものも用意しました。 これで準備完了です。 当日の様子 展示前日の10/26日に荷物を搬入しブース設営しました。設営担当やブース担当などは社内のたくさんのエンジニアメンバーにご協力いただきまして、事前に対応シフトを組んで臨みました。 設営完了。いい感じです! あとは展示会場には出展企業が自由にメッセージを残せるボードがあるのですが、こちらに採用募集ポスターを掲載しておきます。 せっかくなのでイラストも描きました。パンフレットやブースにもフクロウ要素が入っているので、フクロウの会社と覚えてもらえればいいなという思いも込めております。 当日は国際カンファレンスなだけあり、海外からの来場者が多い印象でした。ある程度は予測していましたが、特に初日(10/27)は英語で話をされる方が日本人よりも多い印象でした。 ブースでサービス説明や技術要素の説明などの対応を行います。 出展デモ ブースに来場いただく方にセーフィーのことを知っていただくには、動いているプロダクト・サービスを触っていただくのが一番良いと考えまして、いくつかのカメラをブースに設置しました。 Safie One エッジAIアプリが入った屋内用のカメラ。 safie.jp 三脚を持参し少し高いところから撮影し、ブースに来場いただいた方々の人数をカウントする試みをしてみました。 実際に2日間でカウントされた結果がこちらです。人数は伏せていますが、時間帯によって来場者数の推移が見て取れます。初日の14時ごろが一番来場者が多いようですね。(ちなみに初日は平日でした) この試みはブースに来ていただいた方々にも一定ウケまして、セーフィーが提供しているプロダクトについて、映像の視聴だけでなくデータを使ったソリューションという観点で、一番イメージいただけたものになったのではないかと思います。 Safie Pocket2 Plus 胸ポケットにつけるなどして持ち運びが容易なウェアラブルカメラ。 safie.jp 会場の様子が遠隔でもわかるということを示すために、展示中たまにこちらのカメラを胸につけて、他社様のブースなどに行くなどしていました。 他社様のブースで話を聞いてる際に、「その胸につけてるものはなんですか?」と聞かれることが多く、そのままセーフィーの紹介とブースへの誘致を行うことができたので、話の接点を持つのにも一役買ったカメラでした。 Safie Connect HDMI出力された映像をセーフィーのクラウドにアップロードしどこでも映像を見れるようにできるルーター。 safie.jp 展示にはドローンごと持参し、ドローンの映像を遠隔で視聴するデモを行いました。ドローンを展示することで来場した方々にも覚えてもらいやすくなったのではないかと思います。 撤収と振り返り 社内のいろんな方のご協力のおかげで2日間のブース出展を無事に終えることができました。最後に荷物を梱包し直して撤収します。お疲れ様でした! その後の社内での振り返りとしては、 デモの内容が前回出展時よりもウケが良かったように感じた パネルを用意したため説明がしやすかった ブース担当者は椅子に座らず立つオペレーションだったため、来場した人に声をかけやすかった。結果ブースが賑やかだったと言われた などが良かった点として挙がりました。 一方で、 デモ用のディスプレイはもっと目立つように大きいものを準備すれば良かった 英語による配布物をもっと充実させておけば良かった もう少し企画っぽい出し物もあれば認知に貢献したかもしれない(他ブースでやられていたくじ引きやクイズなど) などの反省点なども挙がったため、次回出展する際には検討できるようにしたいなと思っております。 セーフィーでは継続的にエンジニアへ向けた認知拡大活動を行なっており、各種イベントへの出展・登壇や、このテックブログへの記事執筆もその活動の中の一つです。 今後も継続的な発信を行なっていきますので、よろしくお願いいたします。 セーフィーではプロダクト開発に関わる職種を積極採用中となりますため、興味を持たれた方はぜひ会社概要や募集職種なども見てみてくださいませ! speakerdeck.com open.talentio.com
メリー・クリスマス、セーフィーCTOの森本です。 こちらは Safie Engineers' Blog! Advent Calendar の25日目のエントリーです。 時間の経つのは早いもので、当社も少し前まで数十人でバタバタやっていたように感じていますが、それが今では400人を超え、いよいよ創業10年目に突入しました。 まだまだやりたいこと、やらなければならない事が山積みでそのために更に大きく成長していく必要も感じていますが、現在の姿も過去からの積み重ねですので、今後を考える上でもまずは年末のこのタイミングで今までの歴史を振り返ってみたいと思います。 はじめに 暗黒時代 エンジニア数〜10名 2014年〜2016年 2017年〜2018年 闇からの夜明け エンジニア数〜30名 2018年〜2020年 未来への飛躍 エンジニア数30〜100名 2021年、2022年 2023年 今後に向けて まとめ 最後に はじめに 上記は創業してから今日までのエンジニア人員数、対応カメラの台数、主要プロダクトを表した図です。 カメラ台数は2015年のサービス開始から2019年あたりまで中々伸びず苦しい時期を過ごしましたが、2019年頃からカメラ台数が一気に増加、 2021年〜2022年に一時的に成長が鈍化し、2023年から再度成長軌道に乗っています。 エンジニア人員数はと言うと、上記に合わせたわけではありませんが、同様に2019年ごろまで極めて少ない体制でやっており、少しづつ増加したものの大きな伸びはなく、2022年頃から大きく増員しています。 尚、全体に渡ってコンスタントにプロダクトを出せていますが、チャレンジングなプロダクトが出せるようになったのは2018年からという感じになっています。 engineers.safie.link 暗黒時代  エンジニア数〜10名 2015年5月に満を持してサービスを開始しましたが、中々カメラが売れずビジネス面で苦戦、且つプロダクトの品質もイマイチな状況でとにかくもがき苦しんだ時期でした。 本当に二度と戻りたくないです。 開発体制としてはエンジニア数名〜十名程度なので組織という概念も無く全員で日々のバグ修正や改善、新機能開発を同時に進めていました。 必然的にリポジトリはアプリケーション、バックエンド/インフラ、デバイスには分離しているものの、それぞれが単一のリポジトリで構成されていました。 当時はスピード感という観点でこの状態が最もやりやすかったのは事実です。後々この構成がボディーブローのように効いてきますが。 新機能開発も完全にエンジニアドリブンで、ほぼエンジニアだけでプロダクト開発を進めていました。 上記の通りの品質でしたが、とにかく出すことを優先して活動していました。 2014年〜2016年 創業メンバー2名(プラス業務委託2名程度)で全領域を回していました。 全システムや仕様が頭には入っていたのでテストの仕組みも薄い感じで、簡単に正常系と異常系をテストしてリリースしていました。(今だと考えられないです) 2017年〜2018年 ようやくエンジニアが増え始め、各領域に担当者を立てる事が出来ました。 またバックエンド/インフラは複数人体制(と言っても2名だが)が取れるようになりました。 闇からの夜明け  エンジニア数〜30名 2018年〜2020年 プロダクト、サービス品質の安定化、機能拡充、新商品の提供により急激にカメラの販売台数が伸び始めました。 エンジニア数の増加、プロジェクト数の増加に伴い、問題が発生するプロジェクトも散見されるような状態となり、エンジニアで全てを回していく体制から脱却し、PM/PdM専任者の配置を行いプロジェクトの安定化を図りました。 エンジニアも全員で保守運用や基本サービスの拡充と新プロダクト、プロダクトの開発を同時に行う体制から、分離して開発に当たる体制へ移行していきたいと組織変更を行いました。 エンジニアの総数が圧倒的に少なかったので、結果的に職能で分かれるような形になってしまいリポジトリは今までの構成をそのままキープして進めていました。 残念ながらサービス終了となってしまったものもありますが、様々なプロダクトを上記体制で世に送り出してきましたが、よくやれたなと、驚き、反省とともに振り返っています。 SafieVisitors(サービス終了済み) SafieEntrance(サービス終了済み) 未来への飛躍  エンジニア数30〜100名 2021年、2022年 事業成長とともに2021年の9月にIPOを行いました。 ビジネスが順調に成長し、様々な業界の顧客課題の深堀りを進める中、業界毎に課題が異なる為画一的な対応では厳しく、業界ごとに対応を分けていく必要があるということを痛感しました。 元々会社規模が拡大する中で、職能型組織では今後のスケールに耐えられないのではという思いもあり、2022年BU制度を採用し、業界軸に沿った組織体制に変更を行いました。 各BUにはPM/PdM、エンジニアも配置し、それぞれが単独で顧客とする業界向けのプロダクト開発を進めて行けるようにとの狙いがありました。 同時に認証基盤、デバイス管理基盤、録画配信基盤など共通部分はPUとして横串で配置することにより、業界ごとのプロダクト開発を進めつつ、基盤部分の強化を並列で進めたいという想いもありました。 例によってエンジニア数は十分ではありませんでしたが、採用の強化で対応して行くという事も考えていました。 残念ながら以下ような課題があり、組織として再検討が必要な状態となってしまいました。 採用が思ったとおりに進まずエンジニア数が不足したままとなってしまいました。(以下の理由により比較的経験のあるメンバーしか採用出来なかった事も原因だと感じています。) 組織や担当プロダクトを分割したものの、プロダクトの根幹にあるシステムやリポジトリが適切に分離されておらず、結局複数の組織が同じリポジトリを扱う状態が変わっていませんでした。 複雑なシステムが影響して新規参入メンバーのオンボーディングやキャッチアップに多大な時間がかかってしまう状態となっていました。 システム間の連携の複雑さに起因する細かい障害も度々発生してしていました。(大きな障害に繋がらなかったのは流石と思っています。) BU制への移行を通じて、今まで成長の影に隠れていた各種問題が一気に噴出したと感じました。上記の状態を招いてしまった事を反省しつつ、同時に今後の更なるスケールを実現するためにはこれらの課題解決が必須であるとも強く感じました。 2023年 サービス、事業は上記のような組織の急拡大や変更に伴う課題を抱え踊り場を迎えつつも伸長していました。 しかし組織としての課題を放置するわけにも行かず、開発組織は一旦2021年以前の状態に戻すことにしました。 勿論当時と比べエンジニア数そのものが増加していますし、業務システムやAIアプリケーション開発、データ分析を受け持つエンジニアもいましたので、規模そのものが大分大きくなっていました。 また、ただ戻す事はせず組織課題を解決し、更なる成長を目指すためにエンジニアリングオフィスを設置しました。 エンジニアリングオフィスにはEM陣にも兼務してもらい、以下の取組を進めて行きました。 採用、育成強化(イベントなど認知向上活動も) オンボーディングコンテンツ整備 エンジニアスキルテーブル、キャリアパスの整備 その他組織課題全般 qiita.com また、同時にプロダクト開発に加えシステムの強化、改善も明示的にロードマップに上げ取り組みを進めました。 本記事執筆中の現在、上記の取り組みにより開発組織は安定を取り戻し再度アクセルを踏める状態に推移出来てきたと感じています。 今後に向けて 2022年の踊り場を脱却し、事業は再成長軌道に乗って来たと実感していますが、将来の更なるスケールを実現するためには、BU制移行で露呈した課題の解決が必須だと感じています。 現状のシステムは、結局過去のシステム、リポジトリ構成を多少の修正をしつつ維持してしまっている所が多く、巨大、複雑すぎるために学習効率は元より開発効率や信頼性にも影響を与えてしまっています。また単一で分割に適していない為、組織を分割したとしても結果的に一つのシステムを複数の組織で同時に扱う事となり効率化が進みません。 これを抜本的に解決しなければ、職能型組織からの脱却や開発組織の効率化、拡大など将来の大きなスケールが実現できません。 システムの刷新を行い巨大なシステムを分割し、それぞれの依存度をできる限り小さくすることにより、分割した組織でもそれぞれに対応したシステムを集中して扱う事が出来、開発効率の改善が実現出来ると考えています。 2024年は上記の システムの刷新 対応を進め、確実に一つ以上の実績を出すことを目標に進めて行きます!! システム刷新については以下の記事でも触れられています。 engineers.safie.link まとめ こうやって整理し直してみると、色々な事があったなと感じるのと前もって分割可能なシステムを想定して作っておけばよかったと感じるところもあります。 勿論当時は一刻も早くプロダクトを世に送り出しビジネスとして成立する状態を作る事が最優先だったので、それを同時に行う事は簡単ではありませんでした。 会社には成長段階でそれぞれのステージが存在し、それぞれに適した状況があるというのも理解しており、最初から全てを見越して準備しておくことが今の成長に繋がったのかという疑問もあります。 いずれにせよ大きな理想は描きつつ、失敗も繰り返しながら着実には進化してきていると感じています。 ただ、眼前には今後に向けて超えなければならない システムの刷新 という大きな壁が立ちはだかっています。 最後に システムの刷新 は難易度が非常に高い取り組みですが、今後の成長に向けて我々の意志は決まっています。 一緒に取り組んでくれる人を絶賛募集していますので、興味が有る方はご応募よろしくお願いします!!!! https://safie.co.jp/teams/
はじめに セーフィー株式会社でバックエンド開発のテックリードをしております鈴木敦志と申します。セーフィー株式会社は創業から9年経過し、サービスの拡大と開発者の増加に伴う開発生産性の問題に直面しています。この問題の解消のため、職能横断型チームの再編成とコードベースの分割によるマイクロサービス化を進めています。 セーフィーのサービス・チーム構成 セーフィーのクラウドサービスはカメラ管理および映像閲覧のほか、業務システム、AI応用サービス、開発者向け機能および入退館管理システムなどで構成されており、サーバー/Webの開発者のほかモバイル/組み込み/QAエンジニアなど様々な職種が関わっています。チームは職能別に分かれており、チームごとに複数のプロジェクト (開発案件) に参加します。 開発チーム構成 開発組織の規模が増えるにつれ、様々な問題が明らかになってきました。 機能追加・改修にはたいていWeb・サーバーなど複数職種が関わってくるため、開発に伴い複数チーム間の調整が頻繁に発生します。各チームは複数プロジェクトを並列で掛け持ちすることになり、開発リードタイムの増加と認知的負荷の増加に繋がっていました。 特にバックエンド開発において、モノリシックなサーバーコンポーネントを複数チームで共有しているためコード変更やデプロイ作業の競合が頻繁に発生していました。こういった状況に対処するためにコードベースの分割が進められていましたが、各コンポーネントのオーナーシップが不明確であるためにいわゆる分散モノリスの状態になり改善には繋がりませんでした。 これらの問題を抜本的に解消するため、職能横断型チームの再編成とマイクロサービス化に取り組んでいます。 マイクロサービス マイクロサービス とは、個別にデプロイ可能なサービスの集合体としてシステムを構成することで多人数による並列開発を効率化する手法です。今回は下記方針でマイクロサービス化およびチーム再編成を進めていきます。 マイクロサービス境界を決定: マイクロサービスの導入にはどのようにサービス境界を定めるかが重要になりますが、今回はビジネス機能により分割し、必要以上に細かく分割しないようにしています チームおよびサービス境界の分割 チームの再編成: 各チーム内で開発業務が遂行できるよう企画・QA含め機能を集約し機能横断チームを編成します コンポーネントの分割と内部APIの整備: ソフトウェアコンポーネントの機能がマイクロサービス境界をまたいでいる場合、コードベース・デプロイ単位・DBを分割します。境界をまたいで機能提供を行う場合、gRPC等で内部APIを整備します。 モジュラーモノリスの検討 マイクロサービスに関連する手法としてコードベースおよびデプロイ単位は単一のままモジュールのオーナーシップを明確化するモジュラーモノリスも知られており、マイクロサービス移行の前段階として、あるいはマイクロサービスの複雑さを回避しつつ大規模開発を行うために用いられます。弊社においてはモジュール間参照の規律を保つのが難しいと判断したため、マイクロサービスを選択しました。 既存コードベースのマイクロサービス化 既存コードベースのうち特にバックエンドのソフトウェアはAPIサーバー、デバイス接続サーバー、タスクキュー、バッチサーバー等多数のサーバーで構成され、いわゆるモノリスあるいは分散モノリスとなっています。これらのソフトウェアの機能を保ったままマイクロサービス化を進めるため、以下の手順を取ります。 既存コードベースのうちマイクロサービス境界をまたぐものをチームごとにフォーク 自チームの担当範囲外の実装範囲外を削除またはプロキシに置き換え DBへの接続権限を変更し担当範囲外のテーブルへの書き込みを禁止 マイクロサービス境界をまたぐ機能提供をAPIプロキシまたはDBの参照からgRPC等の内部APIに置き換える DBサーバーを分割 例: カメラ管理と契約・決済情報の分離 場合によっては単純なAPI分割だけではサービスの分割ができず、再設計が必要な箇所があります。 例として、セーフィーではカメラごとに顧客とSaaS契約が締結され、契約プランにより使用できる機能が異なります。契約プランはフロントエンドチームの内製する管理ツールにより操作され、また社内の業務システム (Salesforce, Zuora等) と同期されています。チームをまたいだ複雑なデータの同期が行われ、またどこの情報が元データなのかがわかりづらくなっていました。 現在サーバー内では契約情報とそれにより有効化される機能が単一のRDBテーブルで表現されていますがこれを分離し、カメラの機能有効化API/ライフサイクル管理APIを業務システムチームに提供する形で連携することで、契約情報の一元管理を実現します。 まとめ セーフィーにおけるサービス規模・開発組織規模の増大に伴う開発生産性の問題に対応するため、既存システムのマイクロサービス移行を進めています。 現在セーフィー株式会社ではソフトウェアエンジニアを採用中です。マイクロサービスアーキテクチャや開発生産性の向上についてご興味のある方はぜひともご応募ください。 https://safie.co.jp/teams/
この記事は Safie Engineers' Blog! Advent Calendar 23日目の記事です。 企画本部のマネジメントをしております植松です。 本テックブログももうすぐ丸4年を迎えます(祝!)。テックブログのごく初期に プロダクト(商品)開発の歴史 を投稿してからもSafieは様々なプロダクトを世に出してきました。 そこで、本記事ではこの4年間でリリースしてきたプロダクト群の一部紹介と、今後の展望について書いてみたいと思います。 プロダクト年表 (2020~) Safie API / Safie Developers Safie Pocket2 / Pocket2 Plus Safie One / SPDP 今後の展望 Safie API / Safie Developers 2020年迄はエンドユーザーやパートナーの方向けの製品を作っていましたが、開発者向けの初のプロダクトとして2021年2月に Safie API をリリースしました。 これにより、お客様の既存の業務ツールに我々の映像を組み込んでいただいたり、画像解析をお客様側で行っていただく、など、お客様側の使い方の幅が格段に広がりました。 元々の企画の始まりはパートナー様向けの案件があり、それは画像取得しViewerへのイベント登録をパートナー様側で画像解析して登録する、というものでしたが、我々のサービスとしては汎用化を見据え同時にストリーミングAPIを準備しました。かなりタイトなスケジュールでしたがなんとかリリースにこぎつける事ができました。このパートナー様向け機能については継続的に多くの台数使っていただいて売上高も順調に伸ばしており、今後のAPI利用の足がかりにもなったと思っています。 当初はβ版として限られたユーザにのみ使っていただいてましたが、今年頭から晴れて Developer(Safie API v2) として生まれ変わり、登録したユーザは誰でも使っていただけるようになっています。このブログでは APIの使い方 や、 APIの便利なユースケース も紹介していますので、そちらもぜひご覧いただければと思います。 Safie Developers Topページ Safie Pocket2 / Pocket2 Plus ウェアラブルカメラPocketシリーズは2020年にリリースしたPocket2 , 2023年にリリースした Pocket2 Plus と着実な進化を遂げていますので、その歴史について簡単に記したいと思います。 2020年一番の出来事は何と言っても新型コロナウイルスでした。弊社のサービスもコロナウイルス対策最前線の病院などで活用され、その事例は英国のBBCニュースでも取り上げられました。 そこに遠隔業務の切り札として満を持して2020年7月に登場したのが「 Safie Pocket2 」です。 初代Pocketは、所謂MVP(Minimum Value Product)と呼ばれる仮説検証のため、市販のウェアラブルカメラのソフトウェアをカスタマイズしたものです。静止画スナップショット機能やWebRTCによるリアルタイム双方向音声通話の実現といった新開発機能を盛り込んだ、新しいサービスでした。 私が入社した頃には既に初代Pocketは開発が終わっていましたので、伝え聞くところにはなりますが、カメラ本体に加えて無線LANルーターやモバイルバッテリーが別途必要で、ご利用いただいたユーザー様からもやはり、重い、持ち運びしにくい、というフィードバックを数多くいただいていたようです。そこで、エンジニアが、インターネットで見つけた世界中のウェアラブルカメラメーカー(英語では "body worn camera" と呼ばれます)に手当たり次第問い合わせをし、国内外のこれといった展示会を巡った末に実現したのが「Safie Pocket2」でした。 当初は3月に製造して4月販売開始の予定でした。新型コロナウィルスの脅威が日に日に高まり、外出自粛やリモート勤務が行われる中で、Pocket2をご活用いただけるはず、だったのですが、なんとPocket2の工場まで閉鎖されてしまったのです。メーカーさんが何とか頑張って工場を再開したのに部材も人も揃わない。組立が完成しても、物流が混乱しているので発送したカメラが届かない。お待ちいただいていた皆様にようやくお届けすることができたのは、3カ月遅れの7月になってしまいました。予定よりも遅れてしまいましたが、ユーザー様にはご満足いただき、さらにはテレビ東京 WBSで取り上げていただくなど、社会的にも注目される商品となっていきました。 ここで歩みをとめたわけではなく、使っていただいている中で様々な品質課題や改善要望が上がってきておりそれらを解消すべく、今年の5月に新たに Pocket2 Plus をリリース。ウェアラブルならではの「手ぶれ補正」や、音声品質改善のための「スピーカー通話」、ウェアラブルといいながらも実際には固定して長時間利用されている方も多いため「モバイル給電」などの機能を搭載。より痒いところに手が届く、使い勝手の良さを追求したプロダクトとなっています。来年は海外にも羽ばたく予定です。 Safie One / SPDP 弊社CEOの佐渡島が創業当時から何度も語っていた「かしこくなるカメラ」の実現。Safie初のエッジAIカメラである Safie One は2022年9月にリリースされましたが、このリリースも苦難の連続でした。 CC2 / CC2Lという主力プロダクトの製造会社に開発依頼し、商品コンセプト、ハードウェアデザインについてデザイナーの方とコンセプト固めをして何度もやり取りを行い、試行錯誤を行いながらデザインを決めていきました。その後試作機が届いたのですが、SoCから発生する熱問題(AIを定常的に使っていると熱暴走して停止してしまう)・カチカチ音問題(カメラ内部で音が定常的に鳴る)・IrLED反射問題(レンズの下部に反射して映像にゴーストが発生してしまう)... などなど、大きな課題から小さな課題まで膨大な件数を、1つ1つ潰していきながらプロダクトリリース。 当初の構想から足掛け2年。やっとの思いでリリースした後も安定して量産にこぎつけるまでに様々な苦労がありましたが、現在はぽん置き出来る手頃なAIカメラとしてセーフィーの主力商品となっています。 当然ながら、エッジAIカメラというからには同時並行でAIアプリも開発が必要です。 SPDP という主に店舗で使っていただくための立ち入り検知・通過人数カウント・立ち入りカウントがパッケージされたAIアプリを同時リリースしているのですが、これも途中で1度UI部分の仕様変更に伴った作り直しが入り、今の形となりました。もちろんViewerからスムーズに使える使い勝手の良さは他のアプリと同じ思想で作られています。 vimeo.com 今後の展望 まだまだ書きたいプロダクトは色々あるのですが、長くなってしまうので改めての機会とさせていただき、ここでは今後の展望を記したいと思います。 セーフィーでは「映像から未来をつくる」をビジョンに掲げ、ユーザーの課題を解決するプロダクトを創業当初から作り続けて来ました。今後は、 パートナーであるカメラメーカーをユースケースに合わせて増やしていき、カメラ、特にエッジAIカメラのラインアップや、カメラを使える環境(ネットワーク機器、SIMなど)の提供 よりユーザーの課題に寄り添ったソリューションの提供 映像プラットフォーマーとして技術をさらに活用してもらう方法をAPIやSDKで提供 といったあたりを中心に、セーフィーを使ってくださる方を増やし、セーフィーの映像を使って課題解決出来ることをどんどん増やしていきたいと考えています。 最後に、セーフィーでは新しいプロダクト、サービス、ソリューションを一緒につくっていただけるエンジニアやプロダクトマネージャーを大募集しています。面白そうだな、と思った方はカジュアルに話してみたい、で結構ですので是非コンタクトいただけると幸いです! open.talentio.com
この記事は Safie Engineers' Blog! Advent Calendar 22日目の記事です。 セーフィー株式会社でソフトウェアエンジニアをしている大場です。 2022年10月に子供が生まれました。あれから1年という月日が経ち、育児の大変さを実感してきました。ソフトウェアエンジニアという職種はPC1台とネット環境さえあれば場所を選ばないため、コロナ禍もあり、リモートワークを中心として育児と仕事の両立を図りました。 本稿では育児の中で培ってきたあやし方や寝かしつけ方の回顧録を多少のエンジニア視点を交えてまとめておきます。尚、子供によって合う合わないはありますので、必勝の攻略法は(おそらく)存在しないことをご承知おきください。 爆誕から生後3ヶ月ぐらいまで 〜6ヶ月ぐらいまで 〜9ヶ月ぐらいまで 〜12ヶ月まで 1年を振り返って 爆誕から生後3ヶ月ぐらいまで このフェーズでは如何に寝かしつけることができるか、が重要になってきます。と言うのも、生後間もない赤ちゃんは我々のように寝るという概念を知らないため、眠たくなると不機嫌になります。そして、不機嫌になることで泣いて苦しさを訴えてきます。そしてさらに眠れなくなり、不機嫌に... を繰り返す言わばデッドロックの状態に陥ります。 この状態を打破するには泣き疲れさせるか、睡眠導入ツールを活用するかになるわけですが、泣き疲れさせる場合は30分ほどで寝てくれる場合もありますが、大抵は寝てくれないので睡眠導入ツールが必須になります。 とりわけ、我が子はコリック(黄昏泣き)が酷く、生後3週間ほどから毎日のように夕暮れ時からギャン泣きしました。そこで、何か解法はないかと模索したわけです。 当時活用したツールは抱っこしながら音楽を流すことです。曲はネット界隈で話題となっている反町隆史のPOIZONです。なぜこの曲が有効なのか定かではないですが、一説によると低い音程で一定のリズムを刻んでいることが体内の音に近いということらしい。 反町隆史を交えた実際の検証記事はこちら www.oricon.co.jp 曲の長さは4分ほどですが、我が家の場合は5サイクルほど(約20分)流すと大抵は寝てくれました。寝てくれない時は追加で数サイクル流します。そして、ベビーベッドで横に寝かせた後は耳元で音量を少しずつ下げながら流します。そして次第に深い眠りに入ったら成功です。 ですが、背中スイッチ(横になった瞬間起きてしまうこと)が発動すると振り出しに戻ってしまうため、無事に寝てくれた時は奇跡と思い、一切の物音や足音をたてない忍びの心得が身につきました。 しかし、寝ている時でもモロー反射(驚いた時に手足を広げる原始反射の一つ)はランダムで発動し、これに自ら驚いて起きてしまうというどうやっても回避不能なイベントが存在します。1年を通してみてもこの時の寝かしつけが最も困難であったと思います。 〜6ヶ月ぐらいまで この頃は多少の寝返りはしつつ、テレビをなんとなく観ることができるようになりました。Prime Videoで適当な子供向けの動画を流すわけですが、ある時、特定の動画に対して笑みを浮かべていることに気付きました。 その動画のタイトルは「 卵で色を学ぶ 」で、内容は目玉のついた卵に色をつけて、「ハーイ」と叫びながら画面に迫ってくるものですが、この瞬間が好きだったようです。赤ちゃんは(おそらく)複数のオブジェクトを同時にトラッキングすることができないため、画面一杯で単一のキャラクターを映すようなシンプルなシーンの方が興味を引きやすい傾向にあるようです。 www.amazon.co.jp 一方、寝る方はというと、コリックによるギャン泣きの回数は減っていきました。しかしながら、体重増加に伴い、連日の抱っこで腰痛を発症しており、立った状態で寝かしつけることが困難になってきました。様々なツールを試行しましたが、最終的に行き着いたのは「バランスボール」でした(教えてくれた同僚の方ありがとう)。 寝かしつけの基本動作は上下に揺らすことなのですが、バランスボールがあると、座った状態で上下に大きく揺らすことができるため、腰の負担も少なく割と安定して寝かしつけを行うことができました。ただし、バランスボールから急激に立ち上がると、感覚が狂いバランスを崩してしまい、その瞬間起きてしまう恐れがあるため、体を上下に揺らしながら少しずつ立ち上がるという小技を編み出し、シームレスな移行を実現しました。 ちなみに、私が購入した製品はこちらです。実際にスポーツジムで使われており、空気もほとんど抜けないため、寝かしつけ以外でも利用価値が十分にあります。サイズですが、空気をフルで入れることはなく、空気の量で高さの調整が効くので割と大きめを買った方が良いです。 https://www.amazon.co.jp/gp/product/B00DU46YSA/ 尚、この頃までベビーベッドで寝かせていたのですが、ある日を境にベビーベッドで寝ることが一切できなくなりました。色々試行した結果、床にマットを敷いて一緒に寝たらいけそうだということで、それから床で寝るようになりました。 〜9ヶ月ぐらいまで この頃になると、つかまり立ちとハイハイができるようになりました。我が子はハイハイの速度が異常に速く、Macで作業をしているとキーボードを目掛けて脱兎の如く突進してくるようになりました。記憶力もついてきて、それまでは布団を被っていれば気付かれなかったのですが、布団をはいでくるようになり、手の届く所での作業が困難になってきました。 そんな時は例のごとくテレビで動画を観せるのですが、さすがに卵は観飽きたのか集中力が続かなくなりました。代わりに興味を示したのがPrime Videoの「 モラン 」です。ウサギのモランとヒヨコのピウピウのアニメなのですが、これが大ヒットし、映してる間はテレビにかじりつき、卵に代わる鉄板のコンテンツになりました。こうした番組を一つは見つけておくと、いざという時に大変助かります。 ちなみにですが、モランは大人も楽しめる内容で、私はグッズを買いにいくほどのファンになりました。 www.creativeyoko.co.jp www.amazon.co.jp 寝かしつけの方ですが、バランスボールは子供の成長に伴い、ボールの上で立ってしまうようになり、座った状態で寝かしつけることが困難になってきました。ですが、自分の寝床を何となく理解できるようになり、ツールを使わなくても自分で頑張って寝ようと試行してくれるようになりました。 〜12ヶ月まで この頃になると成長が著しく、歩き始めたと思ったら、いつの間にか走り出すようになっていました。疲れて床に横たわっていると、平然と踏み潰して乗り越えていきます。子供にとっては単なる障害物と認識されているのでしょう。寝かしつけに活用していたバランスボールはいつしか転がして遊ぶようになっていました。 テレビはモランが相変わらずのお気に入りですが、モランは独自のモラン語を話すため、このままでは日本語でも英語でもなく、モラン語を話す子に育つのではと危惧し、他のコンテンツも併用して観せるようにしました。 テーブルの上でMacを開いているとソファによじ登って攻め込んでくるため、最終的にキッチンカウンターで立った状態で作業していました。そうしていると、子供が脚にまとわりついてきて、奥さんと隠れんぼで遊びだします。 寝かしつけは走り回って疲れさせた後は、電気を消せば自分の力で寝てくれるようになりました。寝るまでは一緒に横になって添い寝してあげるのですが、寝返りをする際に裏拳とソバットが飛んでくるので、ガードは崩さないよう注意が必要です。 1年を振り返って 振り返ってみると、この一年は仕事も含め壮絶であり、長いようであっと言う間でした。育児は自分が想像していたよりもずっと難解であり、本稿では語られていないお風呂、ミルク・離乳食、おむつ替えなども含め、日々時間に追われていました。また、これまで通用していたことが次の日から全く通用しなくなる、ということも日常茶飯事でした。そのため、子供の成長に伴い、生活サイクルを適応させていくことが常に求められました。 仕事との両立面では、子供が誕生してからは子供を中心とした生活に激変しました。それまでは、好きな時に開発することができましたが、それは不可能になりました。特に生後間もない頃は育児で1日が終わってしまう、という日も多々ありました。 そのため、限られた時間を如何に有効活用し、効果を最大限に発揮するか、という意識が強く芽生えるようになりました。また、何より、家族の支えにより、仕事に集中できる時間を捻出できるようになったことで、育児と仕事を両立しながら、次第に以前と変わらぬパフォーマンスを発揮できるようになった点も大きいです。 これらの経験を通じて感じたことは、 育児と仕事を分業するのはあまり効率的ではなく、大切なのは互いに助け合う意識を持ち、互いの負荷を減らすことを常に意識する、それが結果的に高いパフォーマンスの維持に繋がるということです。 思考の面では、エンジニアは物事を論理的に考え、必ずそこに解があると信じて止まない生き物ですが、子供の成長を通じて、イレギュラーケースに対してはそういうものなんだな、と思えるようになり、これまで自分が持ち合わせていなかった考え方ができるようになりました。 総括すると、育児を通して、自分自身もまだまだ未熟であると再認識することができ、今年1年は人生の中でエンジニアスキルとは別に、人として大きく成長できた1年になったかなと思います。 ※ご紹介した番組はPrime Video以外にYoutube等でも配信されていますので、お好きな配信サイトをご利用ください。
この記事は Safie Engineers' Blog! Advent Calendar 2023 の21日目の記事です。 はじめに セーフィー株式会社で画像認識AIの開発エンジニアをしている木村(駿)です。主に、エッジAI搭載カメラで動作する人やモノを検出するアプリケーションの開発を行っています。 このAIカメラを使って、弊社では指定したエリアへの人の侵入を検知するサービスや混雑度合いを数値化するために滞留人数をカウントするサービスなどを提供しています。 これらのサービスが、必要な基準や要件を満たしているかどうかを確認するため、QA (Quarity Assureance) 評価を実施しています。具体的には、AIの検出性能や追跡性能のみを評価するのではなく、実際にユーザーが見る値(侵入検知のフラグやカウント数など)が正しく機能しているかを評価します。 このQA評価をするには評価用データ、つまりアノテーションされたデータが必要になりますが、動画のアノテーションデータの作成は非常に大変です。仮にFPS30の10分の動画に対してアノテーションデータを作ろうとすると、1フレームごとに5人映っていれば 30fps×600sec×5=90000個の矩形を手作業でつける必要があります。バリエーションを作ろうと思うと複数の動画のアノテーションデータが必要で、さらに大変です。 そこで、CGで映像を作成し、自動でアノテーションデータを作成できないかと考えました。 今回は、ゲームエンジンであるUnityを使ったCG映像の作成方法と、CGの人物に対して人検知を行った結果および簡易的なQA評価の結果をご紹介します。 はじめに 利用したツール Unity Perception Package CG映像の作成方法 背景を設定 移動経路と動作を設定 人検知の確認 QA評価 まとめ 利用したツール Unity CG映像の作成にはUnityを利用しました。Unityは米国のUnity Technologiesが提供するゲームエンジンで、ゲームを簡単に作るための支援をしてくれる統合開発環境(IDE)です。3Dや2Dのグラフィックスを扱いやすくし、ゲームだけではなく映像の作成にも活用されています。 使用したUnityのエディタバージョン:2021.3.29f1(LTS) Perception Package CGの人物に自動でアノテーションを付与するため、Unityが提供するPerception Packageを利用しました。 Perception Packageは、画像認識モデルの訓練や検証に利用するための大規模なデータセットを生成するためのツールです。以下の動画ように、物体検出タスク向けのBounding Box 2D、セグメンテーションタスク向けのSemantic Segmentation や Instance Segmentation、姿勢推定タスク向けのKeypoint など様々なアノテーションデータを作成できます。今回は人検出なので、Bounding Box 2Dを利用します。 使用したバージョン:1.0.0 CG人物の生成 Perception Packageでは人物の生成が可能です。上記でアノテーションされている人物もアセットではなく生成された人物で、[ 性別、年齢、人種、身長、体型、服装 ] のパラメータをランダムに振って生成することができます。 生成した人物は、通常のUnityのアセットと同じようにC#Scriptやアニメーションなどのコンポーネントを付けることができるため、作成したい映像に合わせて動作させることができます。 CG映像の作成方法 次に、CG映像の作成方法を説明します。ここでは、弊社のAIカメラの機能であるエリア内に滞留している人数をカウントする機能のQA評価をするため、例としてスーパーのレジ待ちで並ぶお客さんを想定したCG映像を作成します。 背景を設定 まず、背景画像を設定します。今回は簡易的に静止画像を背景として、その前景に人を動かす仕様にしました。Unity上の設定方法としては、Camera Object の子オブジェクトとしてPlane Object を作成し、Plane Objectに背景画像を貼り付けます。そして、Camera Object と Plane Object の間で人を動かすことで、画像の前景として人が動く映像を作ります。 今回はこちらのスーパーのレジ付近の画像を背景に設定しました。人を左から右へ歩かせ、☆を先頭にして赤で囲んだ範囲に並ばせようと思います。 移動経路と動作を設定 人物の移動経路や動作を制御するアルゴリズムをC# で実装しました。 ① 画面左側に人オブジェクトを生成し、上図の☆の位置を目標地点として左から右へ歩かせます。 以下のスクリプトで人オブジェクトを現在位置(transform.position)から目標地点(targetPosition)に向けたベクトル (moveDirection)方向へ移動させます。targetPositionはUnityのUIで入力できるよう、public 変数にしています。 public Vector3 targetPosition; public float moveSpeed; Vector3 moveDirection = targetPosition - transform.position; Vector3 deltaMovement = moveDirection.normalized * moveSpeed * Time.deltaTime; transform.position += deltaMovement; ② 目標地点に到達もしくは前に別の人がいたら立ち止まらせます。 以下のスクリプトで前方に人がいるかを判定します。前方のみの当たり判定を得るため、ColliderではなくRaycastを使用しました。 Ray ray = new Ray(transform.position, transform.forward); RaycastHit hit; hasFrontObject = false ; if (Physics.Raycast(ray, out hit, 0.5f )) { hasFrontObject = true ; } 目標地点に到達もしくは前にオブジェクトがあれば停止し、そうでなければ前進させます。 if ( ! hasReachedTarget) { Vector3 moveDirection = targetPosition - transform.position; // 目標地点に到達もしくは前にオブジェクトがあれば停止 if (moveDirection.magnitude > 0.5f && ! hasFrontObject) if (moveDirection.magnitude <= 0.5f || hasFrontObject) { // 停止 transform.position = transform.position; hasReachedTarget = true ; } else { // 前進 Vector3 deltaMovement = vec.normalized * moveSpeed * Time.deltaTime; transform.position += deltaMovement; } } ③ 列に並んだ人オブジェクトは、しばらく時間が経過したら右を向いて再び歩きだしフレームアウトさせます。 if ( ! hasReachedTarget) { ~~~~ // 手順2の処理 ~~~~ } else { // 目標地点に達したので、一定時間が経つまで待ちます。 stayDuration += Time.deltaTime; if (stayDuration < stayTime) { // 一定時間経つまでその場で停止 Vector3 moveDirection = targetPosition - transform.position; } else { // 一定時間が経つと右に体の向きを変えて、再び前進 if ( ! hasRotated) { Vector3 exitDirection = transform.right; Quaternion rotation = Quaternion.LookRotation(exitDirection); transform.rotation = rotation; hasRotated = true ; } Vector3 forwardDirection = transform.forward; walkForward(forwardDirection); } } 以上のアルゴリズムを用いて作成した映像がこちらです。描画されているバウンディングボックスは自動作成されたアノテーションです。 期待通り列を形成してレジを待っている感じの動画が作られています。 人が宙に浮いている感は否めないですが、人検出モデルの性能を評価する分には問題なさそうです。 最後に、QA評価を行う前に、このCGの人物をAIが人として認識してくれるか確かめてみます。 人検知の確認 作成した映像に対してYolov5sで推論したところ、ちゃんと人として検出してくれました! この生成と動作を繰り返す映像を作成すれば、レジに並んだ人数を正しくカウントできているかのQA評価ができそうです。 QA評価 上記の作成方法をベースにレジに並ぶ人数を変動させて30分ほどの映像を作成しました。この映像を用いて、カウントが正しくできているか評価します。カウントは人検出したBBOXの中心が10秒以上エリア内に留まった場合に行い、カウント数は1分ごとに集計しました。 以下のグラフが結果で、横軸は時間、縦軸が1分あたりのAIによるカウント数とGTです。GTはアノテーションデータを用いてカウントした数です。 30分の映像の中で集計間隔ごとの誤カウント数が3、未カウント数が2と、かなり正確にカウントできていることが分かります。 22分あたりの誤カウント+2の原因を映像から探ってみると、背景と同系色の服を着た人物の検出が途絶え、同じ人物を複数回カウントしていることが原因でした。実際のQA評価では背景やカメラアングル、人数などのパラメータを変えてバリエーションのあるデータセットで評価しているので、誤カウントや未カウントを起こしやすい環境や条件などをさらに詳しく分析できました。 まとめ Unity Perception Packageを使って作成したCG映像でQA評価ができることが分かりました。 物体検出タスク以外にも、セグメンテーションや骨格推定などのタスクにも利用できますので、ぜひ使ってみてください。
この記事は Safie Engineers' Blog! Advent Calendar 20日目の記事です 自己紹介と本日のテーマ はじめまして、セーフィー株式会社でSafieの映像サービスを支えるSaaSプラットフォーム プロダクト群のPdMをマネジメントしているマネージャーの光田です。 本日はPdM組織のマネジメントについて、発生した課題と解決のために取り組んでみた施策についてお話しさせていただきます。 自己紹介と本日のテーマ 前提 発生した問題 どうやって解決したか まとめ 前提 PdMの業務は会社によって大きく変わりますが、SafieのPdMの業務分掌は以下となります。 市場調査、企画提案、収益試算 要求定義、要件定義 KPI設計、プロダクト改善 主にWhy/Whatの整理と関係各部署との調整がPdMの仕事、How/Whenの整理と実現がPMの仕事となります。ほとんどのプロダクトでPMMロールをおいていないので、PMMの仕事もPdMの役割に入ってきます。 また、私がマネジメントしている組織はPdMのみ6名で、 映像を閲覧するSafie Viewer カメラの権限などを統合管理するSafie Manager の2つのユーザー向けプロダクトと、これらの情報を制御するプラットフォームシステム(録画日数の制御や、カメラの稼働状況監視、録画プランやオプションなどの管理)のプロダクトマネジメントを実施しています。 発生した問題 PdMのみの組織をマネジメントするようになって3ヶ月程度が経過したところ、1on1などを通じていくつかの課題がメンバーから共有されるようになりました。 PdMのカバー範囲が広すぎる Safieは一般的なSaaSサービスと異なり、カメラやルータなどのハードウェアも扱っています。PdMはビジネス、ハードウェア、ソフトウェア、在庫・物流オペレーションも把握した上でプロダクト仕様について意思決定しなければならず、PdMとして活躍できるようになるまでの学習コストがとても高い状態でした。 個人事業主の集まりのようになってしまう PdMは各々が担当しているプロダクトの成果を最大にするために、プロダクトチームのマネジメントに注力します。するとPdM同士がコミュニケーションをとる機会が減ってしまい、組織としての連帯感が生まれない状況が発生しておりました。 PdM自身が休めない プロダクトに対する意思決定が迅速にできるよう1プロダクト1PdM体制にしていました。体調不良などで予定外の長期休暇を取るとプロダクト進捗が遅れてしまうため、多少無理をしてでも業務を実施せざるを得ないケースがありました。また、PdMの退職でノウハウが引き継がれず、過去の経緯がわからず右往左往するケースがありました。 PdM自身で全て抱えて解決しなければならず、孤独を抱えて業務をこなしていることが明らかとなり、対策を講じることにしました。 どうやって解決したか さまざまな手段をメンバーとともに検討し試してみましたが、最終的に有効な解決策は 『全てのプロダクトにおいてPdM2名体制でプロダクトマネジメントを行う』 ということでした。 PdMは幅広い知識や経験が必要になりますが、それぞれの得意分野があることが多いです。 営業職や事業開発職からPdMになったメンバーはビジネスが、ソフトウェアエンジニアやPMであればソフトウェア開発にキャリアの軸を持ってPdMになっています。 SafieのPdMもそれぞれの得意分野があり、逆にそれ以外の部分については入社後にキャッチアップが必要でした。 PdM2名体制を標準にすることで、ビジネス / ハードウェア / ソフトウェア / オペレーションについて得意分野が異なるメンバを組み合わせてアサインし、相互に教え合う体制を作ることができ、全てに対して知見がなくともPdMとしてプロダクトマネジメントに取り組むことができるようになりました。 また、2名でプロダクトを見ることでお互いの連帯感が高まり、PdMが休めない状況も解決しました。とても単純なこの施策ですが、1名体制だった時よりも安定感が増しプロダクト改善も以前より進むようになりました。 まとめ 現在は上記の施策に加え、組織の連帯感を高めPdMとしての成長を加速する目的で、週次でPdMに関するオンライン講座を受講し、学習内容をサマリーして輪番で発表する会を運営しています。 講座の内容に関連する悩みをメンバーに共有したり、自分だったらこうする、などのノウハウを共有することで、お互いを高めあういいサイクルが出来上がっています。 これからも色々な施策を試しながら、チームの成長に繋げていけたらと考えています。 もし同じ悩みをお持ちのPdM組織のマネージャーがいらっしゃいましたら、参考にしていただけると嬉しいです。 最後まで読んでいただきありがとうございました。
この記事は Safie Engineers' Blog! Advent Calendar 19日目の記事です こんにちは。2023年3月にセーフィーにジョインした入社一年目のQCDグループの森重です。 入社してからはカメラの対応機種拡大やマイページ、モバイルアプリと様々な領域・プロダクトにQAとして携わっていて、テスト設計や手動テストの実行だけでなく自動テストにも取り組んでいます。 この記事ではQCDグループで取り組んでいる自動化、特にMagicPodに焦点を当てて、QCDグループがMagicPodでどんなテストを自動化しているかをお話できればと思います。 MagicPodについて 自動テストの目的 自動テストのスコープ 新機能:ヘルススコア メリット/課題 最後に MagicPodについて そもそもMagicPodとはなんぞや?という方もいると思うので、簡単にツールについて説明します。 MagicPodは有償のテスト自動化ツールでWeb・モバイルに対応したE2Eテスト自動化ツールとなっています。 他の自動テストツールと比べて優れていると思うのは、自動テストの実行回数に制限がない点、メンテナンス性を確保し易い点です。 実行回数に制限がないので、毎日自動テストを実行したいプロダクトに向いているツールと言えます。 自動テストの目的 次にQCDグループで自動化に取り組んでいる目的ですが、これはテスト実行回数増加と広範囲化でバグの早期検出とバグ検出件数増加のためです。 MagicPodに決まったテストを毎日実行させることでエラーを早期検出し、今までリスクベースで切り捨てていたテストもやってもらうことで、カバーできる範囲を増やすようにしています。 自動テストのスコープ 対象のテストは、ずばりリグレッションテストになります。 テスト対象の変更が少なくメンテナンス性の確保が比較的容易なことが大きな理由です。逆にE2Eテストで自動化しないほうが良いのは頻繁に変更が入る新規機能だったり、変更が入りやすい画面を対象としているテストケースです。 実際の画面をお見せするとこんな感じです。失敗しているテストケースもありますが、定期実行して毎日結果をモニタリングしています。 メンテナンスはチームで毎日持ち回りで担当していて、日々やっているという感じです。 新機能:ヘルススコア 少し話はそれてしまいますが、先日のMagicPodのメジャーバージョンアップで追加されたアナリティクスで自動テストのヘルススコアを算出してくれます。参考までにマイページのヘルススコアを紹介しておきます。 マイページ マイページではヘルススコア89です。このプロジェクトはQCDグループの中では後発で自動化を勧めており、パイロットプロジェクトでの運用経験からメンテナンス性を重視したテストケース作成をしています。 特にMagicPodの機能の中でも共有ステップ・変数は様々なテストケースの中の手順を一つの共有ステップで集約することで、テストケースのメンテナンス性・可読性が狙えるため積極的に活用しています。 メリット/課題 一通りテスト対象や運用については書き終わりましたのでMagicPodを自動テストに取り入れたことで感じているメリットと使い続ける上での課題についてもここに書いておきます。 MagicPodを導入したことで感じたメリット 早期バグ検出に役立つ テスト環境を広げたことによるバグ検出ができた メリットですが、こちらはMagicPodを導入した当初の狙い通り、バグ検出関連の恩恵が大きいです。 MagicPodを使い続ける上での課題 テストケースの作成 テストケースの属人化 テストケースの管理・メンテナンス 共有テストケースの活用不足、メンテ工数増 自動テストの実行結果をTesrailに自動でインプットできていない テスト分析 データ分析用の基盤の立ち上げができていないのでスピード感を持った分析が困難 教育 教育資料がなく、ジョインされた方も自己流で学ぶ必要がある 一方課題ですが、MagicPod利用上のルールやそのデータを活用できていないことが多く挙げられています。今後の改善活動として取り組んでいく予定です。 最後に 以上、QCDグループで使っているMagicPodについて紹介させていただきました。 当初狙っていた効果は一定得られているものの、まだまだ課題が残っていますので、継続して改善が必要そうです。 MagicPodにとどまらずテスト自動化について今後もテックブログで発信していきますので、よろしくお願いします。
この記事は Safie Engineers' Blog! Advent Calendar 16日目の記事です。 はじめに Gradioとは Gradioの主な特徴 Hello World! Gradioのインストール コード実装 実行結果 認証機能 リアクティブインターフェース ブロック構造とイベントリスナー コンポーネントの種類 主要コンポーネント一覧 実装例 ソースコード 画面 デプロイと共有 その他ドキュメント 関連記事 まとめ はじめに セーフィー株式会社 開発本部 第3開発部 AIVisionグループで画像認識AIの開発エンジニアをしている土井 慎也です。 セーフィーには2023年1月に入社し、もうすぐ1年が経とうとしています。 今年を思い返せば、生成系AIを中心とした、AI界隈の発展がすごい1年でした。 毎日のようにいろんな技術が発表されて、使えそうなものはすぐにOSSに実装されていて、技術進歩の速度がものすごく速く感じました。 さて、今回はそんなAI界隈で広く使われているWEB UIツールの Gradio について紹介したいと思います。 Gradioとは Gradioは、機械学習モデルを簡単にデモするためのPythonライブラリです。Gradioを使用すると、モデルの入力と出力に対応するインターフェースを簡単に作成でき、モデルを試すためのWeb UIを少ないコード量で生成できます。これにより、AIモデルの挙動を迅速に確認したり、他の人と共有したりすることが可能になります。 Gradioの主な特徴 シンプルなAPI : 数行のコードでUIを構築可能 多様なコンポーネント : テキスト、画像、音声など様々な入出力形式に対応 リアクティブな設計 : 入力変更に応じたリアルタイム更新 認証機能 : ユーザー認証システムの簡単な実装 HuggingFace連携 : Spacesとの統合によるモデルの共有と展開 カスタマイズ性 : レイアウトやスタイルのカスタマイズ stable diffusionで有名なWEB UIの一つである、 stable-diffusion-webui もGradioを使用しています。 AI用のGithubともいえる HuggingFace との親和性も高く、HuggingFaceで公開されているモデルを簡単に試すことができたり、逆に自分のモデルを公開することもできます。 また、機械学習モデルに関係なくても、Gradioには色々なインターフェイスが用意されているので、簡易的なWeb UIが簡単に実装できます。 Gradioは日々アップデートで変化しているため、今回はあまり深くは解説せず、基本的な紹介といたします。 Hello World! python3.8以上が実行可能な環境を用意します。 Gradioのインストール pip install gradio コード実装 import gradio as gr def greet (name): return "Hello " + name + "!" # インターフェースの作成 # fn: 実行する関数 # inputs: 入力のコンポーネントの種類 # outputs: 出力のコンポーネントの種類 demo = gr.Interface(fn=greet, inputs= "text" , outputs= "text" ) # Web UIの起動 demo.launch() このように、わずか数行のコードで、簡単にWeb UIを作成することができます。 HTMLやCSS、JavaScriptなどを意識する必要はありません! 実行結果 https://gradio-hello-world.hf.space 認証機能 Gradioには認証機能が組み込まれています。 demo.launch(auth=auth_function) とすることで、認証機能を有効にすることができます。 認証機能のベースはFastAPIの OAuth2PasswordRequestForm を使用しているようです。 import gradio as gr def greet (name): return "Hello " + name + "!" # 認証機能 def auth (user_name, password): # 例: ユーザー名とパスワード(反転)が一致したら認証OK # 実際にはDBと連携して認証するなどの処理が必要 if user_name == password[::- 1 ]: return True else : return False demo = gr.Interface(fn=greet, inputs= "text" , outputs= "text" ) # 認証機能を有効にする demo.launch(auth=auth) ログイン画面イメージ リアクティブインターフェース gr.Interface で live = True を指定すると、入力値を変更するたびに、リアルタイムで出力が更新されます。これにより、ユーザーは即座にフィードバックを得ることができ、インタラクティブな体験が向上します。 import gradio as gr def calculator (num1, operation, num2): if operation == "add" : return num1 + num2 elif operation == "subtract" : return num1 - num2 elif operation == "multiply" : return num1 * num2 elif operation == "divide" : return num1 / num2 # リアクティブインターフェースの作成 demo = gr.Interface( calculator, [ "number" , # 数値入力 gr.Radio([ "add" , "subtract" , "multiply" , "divide" ]), # 演算子選択 "number" # 数値入力 ], "number" , # 出力は数値 live= True , # リアルタイム更新を有効化 ) demo.launch() https://gradio-calculator-live.hf.space ブロック構造とイベントリスナー Blocksを使用すると、より細かくレイアウトを指定することができます。Interfaceよりも柔軟なUIデザインが可能になり、複雑なアプリケーションの構築に適しています。 また、イベントリスナーを使用することで、ボタンをクリックしたときの処理を指定することができます。これによりユーザーインタラクションに応じた動的な振る舞いを実装できます。 Hello World!をBlocksを使用して書き換えると、以下のようになります。 import gradio as gr def greet (name): return "Hello " + name + "!" # Blocksでレイアウトを構築 with gr.Blocks() as demo: # 入力コンポーネント name = gr.Textbox(label= "Name" ) # 出力コンポーネント output = gr.Textbox(label= "Output Box" ) # ボタンコンポーネント greet_btn = gr.Button( "Greet" ) # イベントリスナー: ボタンクリック時にgreet関数を実行 greet_btn.click(fn=greet, inputs=name, outputs=output, api_name= "greet" ) demo.launch() https://gradio-hello-blocks.hf.space 詳しいBlocksとイベントリスナーについては公式ガイドをご参照ください: www.gradio.app 詳しいレイアウトの方法について www.gradio.app コンポーネントの種類 Gradioには多種多様なコンポーネントが用意されています。一般的なものだと、text, number, checkbox, radio, dropdown, file, button, slider などがあります。 また、AI開発に特化した画像や音声、動画、グラフ、チャットなどの様々なコンポーネントも用意されています。これらを組み合わせることで、様々なAIモデルに対応したUIを構築できます。 主要コンポーネント一覧 基本入力 : Textbox, Number, Slider, Checkbox, Radio, Dropdown メディア入力 : Image, Audio, Video, File 高度な入力 : JSON, DataFrame, ColorPicker 出力表示 : Label, Image, Audio, Video, Plot, Gallery レイアウト : Row, Column, Tabs, Accordion コンポーネントの詳細な種類は公式ドキュメントをご参照ください www.gradio.app また、Gradioのメジャーアップデートでカスタムコンポーネントも最近追加されたので、今後ユーザーによって多くのカスタムコンポーネントが実装されていき、より種類が豊富になっていくと思います。 カスタムコンポーネントの作成方法 www.gradio.app 実装例 最近発表され、話題になっている動画生成AI、 MagicAnimate のWebUIになります。Gradioを使って洗練されたインターフェースが実装されています。 ソースコード huggingface.co 画面 https://zcxu-eric-magicanimate.hf.space zcxu-eric-magicanimate.hf.space デプロイと共有 Gradioで作成したアプリケーションは、様々な方法でデプロイ・共有することができます: ローカル共有 : demo.launch(share=True) でトンネリングURLを生成 HuggingFace Spaces : 無料でホスティングできるプラットフォーム 自前サーバー : FastAPIなどと組み合わせて独自サーバーにデプロイ 特にHuggingFace Spacesとの連携は簡単で、GitHubリポジトリを接続するだけで自動デプロイが可能です。 その他ドキュメント 公式ガイドとドキュメントを参照すると、より詳しい情報が得られます: www.gradio.app www.gradio.app 関連記事 実際にアプリを作ってみた記事です。良ければご覧ください。 engineers.safie.link まとめ Gradioが用意しているコンポーネントで事足りる場合、それらを組み合わせることで、AIに関わらずPythonで作られたソフトウェアは簡単にWeb UIを作成することができます。 フロントエンドの知識がなくても、簡単かつ迅速にWeb UIを作成することができるので、Pythonで開発したものをすぐにWebアプリ化したいAIエンジニアなどにとっては、非常に便利なツールだと思います。 セーフィーでも、Gradioを使用して社内向けに気軽にAIを試せるデモ環境を迅速に用意し、PoCやその他検証などに活用できないかを現在検証しています。
この記事は Safie Advent Calendar 15日目の記事です。 はじめに こんにちは。開発本部モバイルグループの池田です。 私は普段、モバイルグループのマネジメントおよび Safie Viewer for Mobile の PdM としてお仕事をしていますが、今年はそれに加えて 国際化対応 の開発PMとしても活動してきました。 今年の初めに海外展開のための組織が立ち上がり、そこの社内募集に手を上げて、兼務でお手伝いすることとなったためです。セーフィーではこのように、社内でも新しい試みにチャレンジしやすい制度が整っています。 実は、2023年中にセーフィーはグローバル進出のためのビジネス立ち上げ準備と開発を進めており、Safie Viewer モバイルアプリは英語・ベトナム語・タイ語への対応をリリースしています。また時差対応もほぼ完了し、以前はいくつか問題のあった日本以外のタイムゾーンでも、正しく快適に使えるようにアップデートされています。 エキゾチックSafie!! 今回は、主にモバイルアプリの開発に着目して、セーフィーのグローバル対応について書いてみたいと思います。(Web フロントエンドやサーバー、デバイスについても近々きっと書いてくれる人がいると思います!) はじめに 国際化(Internationalization)と地域化(Localization) 言語について 翻訳について 翻訳について・2 翻訳課題:ベトナム語意外と横長問題 翻訳課題:テキストデザインとFigmaのローカライズ 時間について おわりに 国際化(Internationalization)と地域化(Localization) ソフトウェアを異なる地域や時間に対応するためには、(トートロジー的ですが、)それが「 対応できるようにする 」必要があります。 扱う言語や地域に汎用性を持たせて、たとえばテキストをソースコードから分離して異なる言語に翻訳しやすくすること、また日付や通貨のフォーマットを動的に変更できるようにすることなどが含まれ、この作業を「国際化」と呼びます。この仕組みはすでに OS やプラットフォームにも含まれている部分が多くあります。 そうして国際化に対応したソフトウェアを、今度は特定の言語・地域に適合させるプロセスを「地域化(ローカライズ)」と呼びます。テキストの翻訳や日付・通貨フォーマットの現地化などの作業がこれにあたります。 一口にローカライズと言っても、そこには多くの要素が含まれます。 言語と文字コード、日時や数値の書式、暦、時差とタイムゾーン、各国の通貨や税金、法規制(電波関連法規や個人情報保護関連法規)への対応などなど。あるいは文化的な背景から利用・推奨できない表現やシンボルがあるかもしれません。ヘルプやユーザーサポートをどうしていくかも重要になってきます。 本記事では、その中でも特に大きな割合を占める 多言語対応とタイムゾーン対応 について触れていきたいと思います。 (どうでもいいですが、 i18n (internationalization) や l10n (localization)という略語、知っててもなかなか使う機会がないので今年はたくさん使えて満足です。笑) 言語について 冒頭にも触れた通り、今年の前半にキックオフされたグローバル進出PJにより、Safie Viewer は 英語、ベトナム語、タイ語 に順次対応していくこととなりました。 モバイルアプリの開発環境である XCode や Android Studio には、すでに言語ローカライズのための仕組みが用意されています。 iOS の場合は、XCode のプロジェクトの設定で ”Localizations” から対応言語を追加して、生成された Localizable.strings ファイルにその言語でのテキスト定義を追加していけば基本的に OK です。これらを追加することで、OS やアプリごとの言語設定に応じて、UIに表示される言語が切り替わってくれます。簡単ですね。 XCode プロジェクトの Localization また、リソースファイルの型安全性やオートコンプリートを提供してくれる R.swift の利用によってローカライズ開発の生産性を上げてもいます。 ベトナム語の Localizable.strings ファイル さて、アプリ UI の多言語化の方法はわかりましたが、アプリに表示される文字列は自らが持つリソーステキストだけではありません。 たとえば動的に変化する設定可能な項目を API で取得して、そのリストを選択メニューに表示したりします。あるいはサーバー側で定義された任意のお知らせメッセージを出したりもします。これらの中にはアプリが予め定義しておくことができないものもあります。 API から返却するレスポンスの言語をクライアントによって変えてもらうにはどうしたらいいでしょうか。それには大きく2つの方法があります。 ひとつは、ユーザーの属性として言語設定を持たせ、それをサーバーで判定して言語を切り替えること。ただしこれはユーザーがログイン済みの場合に限られ、いくつかの匿名 API(購入前お問合せとか)では対応できません。また、環境によってユーザーが言語を変えたい時(職場の PC は英語なんだけどスマホは日本語とか)なども対応が難しいです。 もうひとつは Accept-Language リクエストヘッダを利用することです。これはクライアントがどの言語を理解できるか、どのロケール(地域情報)が推奨されるかのヒントをサーバーに示すものです。一般的なブラウザや HTTP クライアントライブラリは環境から設定を読み取り、ユーザーが意識せずともすでにこのヘッダをリクエストに付加してくれている場合が多いようです。 今回は、これらをハイブリッドに対応することにしました。 すなわち、ユーザーには使用言語の設定を追加して、下記表のような選択を可能とする。且つ、それぞれの場合の Accept-Language を表のようにクライアントで付加して、サーバーでレスポンスを切り替えるようにします。 Webアプリ ユーザー言語設定 クライアント UI Accept-Language サーバーレスポンス メール、PUSH通知 システム(自動設定) ブラウザ設定に従う ブラウザ設定に従う ALに従う ALが無ければ日本語 ALがSafie非対応言語なら日本語 日本語 日本語 日本語 ja 日本語 日本語 英語 英語 en 英語 英語 ベトナム語 ベトナム語 vi 英語 英語 タイ語 タイ語 th 英語 英語 ※サーバー対応言語は日・英のみ モバイルアプリ ユーザー言語設定 クライアント UI Accept-Language サーバーレスポンス メール、PUSH通知 システム(自動設定) OS/アプリ設定に従う OS/アプリ設定に従う ALに従う ALが無ければ日本語 ALがSafie非対応言語なら日本語 日本語 日本語 OS/アプリ設定に従う OS/アプリ設定に従う 日本語 日本語 英語 OS/アプリ設定に従う OS/アプリ設定に従う 英語 英語 ベトナム語 OS/アプリ設定に従う OS/アプリ設定に従う 英語 英語 タイ語 OS/アプリ設定に従う OS/アプリ設定に従う 英語 英語 ※サーバー対応言語は日・英のみ ※モバイルのUI言語はセーフィー設定よりもOS/アプリ設定を優先 このように定義した上でデフォルト設定を「システム(自動設定)」とし、且つ「不明な場合は日本語を優先」とすることで、すでに日本語環境でセーフィーを利用している大半の既存ユーザーには影響がなく、その中でブラウザやスマホを英語やベトナム語で使っている人がいれば何もせずその使用言語に切り替わり、さらに明示的に言語を切り替えたユーザーには、メールやPUSH通知といったサービスも言語切り替えをすることができます。 翻訳について さて、言語表示仕様とテキストデータの外出しは終わったので、次は翻訳です。 まず英語は社内でなんとかなるだろうと考えました。アプリ UI に表示されるメッセージの類はある程度形式化されていますし、昨今の deepL や ChatGPT などによる AI 機械翻訳は非常に優秀と言われます。迷った時には社内にいる英語話者を頼ることもできそうです。 どうにもならなさそうなのがタイ語とベトナム語です。機械翻訳できたとしてもその精度がどうなのかまったくわかりません。 ここは素直に専門家を頼りましょう。ということで、いくつかの技術翻訳の会社に見積もりを取り、またいくつかの SaaS 翻訳プラットフォームも検討しました。その結果、ある程度老舗として実績があり、またある程度細かく相談もできそうな会社さんに翻訳依頼を出すことに決定しました。 その際、 日本語→タイ・ベトナム語よりも英語→タイ・ベトナム語の方が精度が高い というアドバイスを受け、まずは初回だけ社内で行った英訳にチェックを入れてもらい、英語からタイ・ベトナム語への翻訳依頼としています。 (ちなみにその英語チェックではほとんど赤が入らなかったので、社内+機械翻訳で充分いけるという確信を強めることができました。AIの恩恵に喜びながらも、翻訳業界は大変だろうなという思いもありつつ。。) 翻訳について・2 翻訳会社さんとのやり取りは Excel ファイルでのシンプルなものでした。 その際、 サービスで利用する固有名詞のルールをまとめて伝えることは重要です。 セーフィーであれば「『カメラ』は基本的に”Device”で表します。ただし表現的にスマホと紛らわしい場合は”Camera”も使います」とか、「 “Movie Clip” は他言語でも英語のままで」など。 また、 スクリーンショットは可能な限りすべてお渡ししましょう。 数十画面・数千ワードという翻訳になるので、ある程度は機械的な作業にならざるを得ず、すべてのサービス文脈を読み取ってもらうことは難しいですが、それでも「ここのスペースにだいたい収まるようにできませんか?」とか「英語での文字幅と同じくらいにできますか?」などのやり取りができる余地を作っていくことも非常に重要です。今回は最初に「基本的に英語でのテキスト幅を越えないようにしたいです」とお伝えしていました。 日付や通貨のフォーマットについてはどうしたら良いでしょうか。 各言語での日付表記 これについては、Google の developer documentation style guide を参考に実装しました。日本語でよく見るスラッシュ区切りの「年/月/日」は他地域ではあまり利用されないなど、様々な知見がありがたく集まっています。 また、Excel(社内では Google スプレッドシートで管理)データのソースコードへの組み込みですが、さすがにコピペではやってられません。ここはスプレッドシートから iOS/Android で必要なリソースファイル(Localizable.strings, values**/strings.xml)へ変換して書き出す Google App Script を書いて省力化しました。 Google App Script による言語リソースファイルの書き出し ただしこの方法では、言語定義の神様(マスター)が GitHub 管理の外になってしまい、メンバーが各自のブランチで神様データをエクスポートして作業すると、それらをマージするとき多重に定義が追加され、コンフリクトが発生してしまいます。 そこで、今度はリポジトリ中のリソースファイルをまとめて csv ファイルを作成し、それを Google スプレッドシートにアップロードする GitHub Actions のワークフローを書いて、リリースごとに神様データを自動更新していくことにしました。 GitHub Actions によるローカライズ対応スプレッドシートの更新 より効率的な翻訳対応にはまだ改善余地があると思いますが、一旦このような形に落ち着いています。 ちなみに翻訳依頼の頻度としては、英訳はリリースごとに社内で対応し、タイ・ベトナム語はある程度溜まってきた数ヶ月ごとに発注するとして、その間はタイ・ベトナム版には英語が混在することを許容する、といった仕様にしています。 翻訳課題:ベトナム語意外と横長問題 日本語を英語にしたとき、文字数が増えてレイアウトが横長になることへの対応が必要なことは予想していました。 その上で意外と大変だったのがベトナム語です。 日本語とベトナム語のフッタメニュー 英語よりもさらに長い表現になることが多く、QA 確認ではテキストの見切れ指摘が多発しました。 ここは、「ユーザー設定」→「設定」などテキストをシンプルにできないかを検討するとともに、レイアウトに収まらないもののいくつかは英語に戻すことで対応しました。 ここについては複数の著名なアプリをベトナム語設定で見てみて、このくらいは英語でもOKかなという肌感をひとまずの根拠としています。 メジャーなアプリのベトナム語対応例 さらに理想なのは、テキストがなくてもメニューの意味がわかってもらえることですね。ここは自らの認知度とデザイン双方に対しての自信が必要なところだとは思います。 メジャーなアプリのフッタデザイン それぞれ、どれが何のアプリか、わかりますでしょうか? 翻訳課題:テキストデザインとFigmaのローカライズ たとえば、これはあくまでも例ですが、このようなダイアログの本文をローカライズするとします。 カメラ再起動の警告ダイアログサンプル 言語リソース定義は以下のように分解すれば対応できます。 “restart_dialog_text_prefix” = “再起動中は”; “restart_dialog_text_body” = “録画が停止します”; “restart_dialog_text_suffix” = “ので、しばらく経ってからご確認ください”; 英語はこう。 “restart_dialog_text_prefix” = “”; “restart_dialog_text_body” = “Recording will be paused”; “restart_dialog_text_suffix” = “ during the reboot, so please check back after some time”; このようにして、prefix, body, suffix を結合し、 restart_dialog_text_body を赤文字のボールドで装飾するルールにすれば、近い表現の英語になると思います。 しかし、ベトナム語やタイ語ではどうなるのでしょうか。語順がどうなるかわからないし、翻訳者に細かいニュアンスを伝えることも手間がかかりそうです。 こういったことを防ぐためには、 できる限りテキストはシンプルにすること(説明無しでわかるUIが最高) テキストの一部を装飾する場合は少なくともセンテンス単位にして、一文を短くすること などを心がけることが大事になりそうです。ここまでがワンセンテンスだ、よろしいか? デザインの段階で、国際化を意識した作業ができていると良いですね。 また、今回は既存のアプリをローカライズするという要件と、スケジュールの都合もあり、レイアウト調整などの作業もすべて開発チームで行いました。が、本来は社内で英訳までするのであれば企画・デザインの段階で各言語での見た目を確認できた方が良いはずです。 過去の記事でも触れたように、モバイルチームでは デザインのやり取りに Figma を利用しています。 Figma 上でのローカライズ方法もこれから調査・検討していくところですが、 lokalise などのサービスは試してみたいなと思っています。 時間について さて、言語の話だけでずいぶん長くなってしまいましたが、お次は時間(タイムゾーン)についてです。 幸いにして、セーフィーのサービス開始当初から、データベース内の時間はすべて UTC で管理されており、また多くの時間関連 API はリクエストに timezone のパラメータを受けて、その時間帯でのレスポンスを返せるようになっていました。(先見の明!) なので、クライアントとしては基本的に現在の OS のタイムゾーン設定をリクエストパラメータに追加するだけで良さそうです。が、むしろここで悩んだのは仕様の方です。 Safie 三位一体 セーフィーのサービスを構成する基本3要素、カメラデバイス、クラウドサーバー、ビューアークライアントは、地理的にすべて別の場所にいることがありえます。それぞれに OS があり、それぞれのシステムに時間とタイムゾーン情報を持っています。 タイのバンコクに置いたカメラを、ハワイで休暇中のユーザーが見ている時、ビューアーに表示される時間はどこになるのが良いのでしょうか?セーフィーは東京に本社がある日本のサービスですが、そこから「xx時xx分にカメラが動きを検出しました」というメールが来る時、その時間帯はどこになるのが正しいのでしょうか?夜間だけ録画するようにタイマーを設定する UI の時間はどう見せましょうか? ここもおそらく議論の余地があると思いますが、結論としては クライアントの UI で表示・設定する時間はすべてクライアントの(PCやスマホに設定された)タイムゾーンに従う ただし、カメラ映像に重畳して録画される時間情報は、カメラデバイスのタイムゾーンに従う これは例えば犯罪行為のエビデンスとして映像上に表示された時刻が用いられることがあることを重視して、カメラが見ている「その場所」のタイムゾーンを優先しています メールに記載する時間については、デバイスに関連するものはそのタイムゾーンに従い、”(UTC+09)”といった注記を加える PUSH 通知に載せる時間情報は epoch ミリ秒で表し、受け取ったクライアントは自分のタイムゾーンで適切に再生処理する などのルールを定めました。 Viewerの時間表示 この対応のため、JST 固定になっていたデバイスのタイムゾーンを可変にできるよう FW を更新してもらい、サーバーとカメラの I/F やメールテンプレート生成などのロジックを変更してもらった上で、クライアントは先述の通りリクエストにタイムゾーンを付加するだけでほぼ対応が終わりました。サーバー・デバイス各チームの尽力に感謝です。このあたりの実装のお話もいつかエンジニアブログで読んでみたいところ。 ちなみに、今回はできるだけシンプルな対応にとどめていますが、タイムゾーンは突き詰めると考えなくてはならないことがたくさん出てくるようです。気になった方は有名な魔導書「 タイムゾーン呪いの書 」を読んでみてください。 おわりに 日本語と日本時間を前提としていたサービスを、国際化・ローカライズした活動について、ひとまずアプリ視点からのまとめを書いてみました。その後、面接で海外からの候補者がアプリの話をしてくれた時に、英語で何も違和感ないですよと言われてひそかに喜んだりなどしています。さらに対応を拡げていきたいですね。 文中で何度も触れているように、この PJ はモバイル以外も各チーム対応に尽力いただいたので、そちらはぜひ別記事を楽しみにしていていただきたいと思います。(ちなみに国内サービスが初めて海外展開をする際に、多くの場合最も重要なトピックは「クラウドインフラどこでどう構築する?」になると思います) グローバルを見据えたサービス開発をする方々に、参考になる情報があれば幸いです。 また、セーフィーでは一緒に世界を目指すエンジニアも募集しています!興味をもった方はぜひ こちら へどうぞ。 open.talentio.com
この記事は Safie Engineers' Blog! Advent Calendar 14日目の記事です。 こんにちは、あるいはこんばんは 第1開発部QCDグループ 小山と申します。 ブログ書きますよからもう1年、 さすがに筆を走らせないと追い込まれてしまうので… 今年もいろいろありましたが、ブログのネタにできる変化としてはテスト管理ツールの運用を始めたことでしょうか。 こちら導入時の動機、想定していたメリット・デメリットや、運用開始後上手くいった・いかなかった点について記載していければと思います。 テスト管理ツールを導入したいと考えている方にとって少しでも役立てれば幸いです。 1. 使ってみたいと思った不純な動機 2. 導入前に享受できると思ったメリット・デメリットについて 導入前想定メリット 導入前想定デメリット 3. 上長からの反応(主観的な振り返り) 4. 運用開始直後の振り返り 1. テストにまつわる工数の削減(上手くいっている) 2. テストケースの資産化(どちらかというと上手くいっていない) 3. テスト状況の可視化、レポート作成工数の削減(どちらかというと上手くいっていない) 4. BTSとの連携(どちらかというと上手くいった) 5. 管理ツール内の情報(実施結果等)を共有する場合(上手くいっていない点) 6. 入力工数の活用(上手くいっていない点、課題) 7. 自動化ツールとの連携が出来ていない(上手くいっていない点、課題) 5. まとめ 1. 使ってみたいと思った不純な動機 Googleスプレッドシートでの進捗管理がめんどくさくて仕方がない… これが私の大きな原動力でした。 というのも、弊社はスプレッドシートで作成されたテストケースを用いて定期リリースに向けたテストを実施しているのですが、 光栄なことに複数のプロダクトの担当を任せていただいていたため、 予定したテストの終了確認と日々の進捗確認が非常に手間でした。 少し細かい内容ですが、 テスト項目数が多いため縦に長く、且つ環境ごとに実施するため横にも広がり… うっかり1項目を飛ばしてしまった場合、探すのが大変という状況でした。 (〆作業を行う為のスプレッドシートとのにらめっこが嫌で嫌でしかたがなかった) ※ちゃんとリグレッションテストを改善しろよというごもっともなツッコミは無しでお願いしますmm また何度も使うテストケースなので、コピーして過去に入力した結果欄を消すのも、めんどくさくて嫌でした。 (メンテナンス工数をうまく捻出できず秘伝の継ぎ足しタレ状態に) 2. 導入前に享受できると思ったメリット・デメリットについて 紆余曲折あり、無料ツールでの失敗から始まり有料ツールのトライアル利用を経て、 まずは1年使用できることがグループ内で合意でき、上長の承認もいただけました。 ここでは、 こんなことが出来るようになるだろうなという導入前に想定していたメリットをつらつらと… 導入前想定メリット テスト管理工数の削減(1PJの定期リリース1回に際し,15分×10営業日程度を想定) テストケースの資産化、再利用ができるためテスト準備の工数削減になる テスト状況の可視化、レポート作成工数の削減 自動テストツールとの連携による、テスト実施内容の可視化 PJごとにばらつきがちなテスト粒度が、同じツールを使用することで均一化 管理ツール導入により何か全体的に改善されるのではないかという漠然とした期待 導入前想定デメリット テストケースの移行コスト(プロダクトによっては1か月弱かかる可能性も) 一度導入するとやめることが難しい、エクスポートしてから加工するなどスプレッドシートでは無かった新たなコストがかかってしまう恐れ テストケースレビュー方法の再検討(アカウント数に上限があるツールだったため) 上記を想定しメリットで納得いただけるよう準備したつもりでしたが、いまいち上手くいかず… 自戒の意味も込めて、メリットに関する反応を主観的に振り返りたいと思います。 3. 上長からの反応(主観的な振り返り) 反応〇 テスト管理工数の削減 再利用によるテスト準備工数の削減 反応△ テストケースの資産化 テスト状況の可視化、レポート作成工数の削減  ※自動テストとの連携、ばらつきについては承認時には明記せず口頭での説明  ※その他デメリットについては理解はいただけたと感じています 上長の立場を鑑みた際、 年額の費用が発生するため、想定通り社員工数の削減が強めな説得材料になりました。 導入前に予想していたよりも、テストケースの資産化は刺さらずという結果は、 説明が下手だった可能性が一因にあったと反省しています。 最終的にはQCDグループが今後も将来拡大していく旨、及び、 現場の負担が軽減されるならという理由で承認いただけました。 おまけ:グループ内で出た「スプレッドシートでいいじゃん」をあらためて振り返ると テスト管理ツールを導入したいですと希望した際、 きっと他メンバーから上がるであろう伝家の宝刀「スプレッドシートでいいじゃん」に対しての振り返りです。 当時はうまく返答できませんでしたが、今返す言葉を考えるとしたら以下になると思っています。 テストを資産として残し”やすい” (保管場所が統一される) フォーマットがある程度決まっているため、テストの実施体制を整え”やすい” (個人による差分が出来くい) テスト管理体制を工数を多く使用することなく構築し”やすい” (計算式の修正から解放される) ただ、ツールの学習コストや移行コスト、テスト設計の自由度まで鑑みてしまうと、どちらに分があるのかは導入後の現時点でも明言は出来ない状態です。 明言はできないものの、推進派一意見としては、 管理ツールを使うことにより将来的に実現したいことを考える機会が得られ、 次のステップを見据えることが出来たのでよかったと思っています。 4. 運用開始直後の振り返り ここからは、導入してどのように使っているか、活用できているか、上手くいっていない運用など、 軽く紹介できればと思っています。 導入したテスト管理ツール: Testrail ( https://www.techmatrix.co.jp/product/testrail/ ) いつも細やかなサポート対応ありがとうございます。 1. テストにまつわる工数の削減(上手くいっている) 他メンバーの協力を得てテストを行う案件が多い中、日々の進捗や成果物確認については楽になったと思っています。 プロダクトにより大小はありますが、 1PJの定期リリースに際し、【10分~20分×テスト期間の営業日】は削減が出来ているかと。 例:1クリックでステータス毎のテストケースの抽出ができる(すごく便利) ※「Pass」ステータスとなっているテストを抽出した結果 また、マスターテストケースを作れるプロジェクト形式を選択すれば、 テストの資産化(再利用または不具合流出時の過去結果の参照など)は上手くいくと思います。 <運用一例> マスターテストケース(v1.0)からv1.1ベースラインを切り出す ⇒テスト終了後、マスターテストケース(v1.0)にv1.1エンハンス個所を反映させる  ⇒次ver開発時にマスターテストケース(v1.1)からv1.2ベースラインを切り出し   ⇒v1.1実施内容も実施時のまま保管することが出来る ベースライン切り出し時に、 どのテストケースを対象とするか、及び、フィルター後も動的に更新するかなどを選択でき、 スプレッドシートでのセル削除や非表示、項目数計算式の修正等からも無縁の状態となりました。 SubVersionを利用している環境下でも同様のことが出来ますが、 「v△△時の○○というテスト結果を探す」という状況ではテスト管理ツールの方が検索性は向上していると思います。 例:次テストケース作成時における参照元の選択 例:更新したMasterテストケースから実施するテストのフィルタリング ※動的なフィルタリングができるのでテスト更新時にももれなく対応できました。 2. テストケースの資産化(どちらかというと上手くいっていない) テストケースの再利用という点はうまく運用できていますが、 たとえば過去の結果を振り返るといったような、資産化による価値はまだ享受できていません。ここは今後の課題。 3. テスト状況の可視化、レポート作成工数の削減(どちらかというと上手くいっていない) テスト終了時のレポートは、標準テンプレートを利用すればクリックのみで作成・提出することは可能です。 ただ、プロジェクトごとに欲している内容は異なっているため、上手くいっているところと活用できていないところ両方あるのが実情です。 とはいえ、直近で行われたTestRailのバージョンアップにより、 TestRailとBTS連携を行っていれば信頼度曲線をすぐに出力することが出来るため、 今後プロダクトが成熟したときに活用できるのではないかと考えています。 4. BTSとの連携(どちらかというと上手くいった) 結果入力時に欠陥にBTSのキーを入力することで、 別ページではなくテストケース上で詳細内容を確認できるようになっているため、 作業効率は上がったと考えています。 しかしながら、 テスト内容をもとにBTS側にチケットを発行できる機能もあるのですが、 フォーマット等調整中のため上手く実運用で使用できておらず、今後の課題となっています。 5. 管理ツール内の情報(実施結果等)を共有する場合(上手くいっていない点) 現在QCDグループでは、 テスト実施前にテスト観点やテスト範囲・対象の認識合わせを行ったうえで、 テストケースの作成を行い、実施しています。 テスト観点等については従来通りスプレッドシートを使用することが多いため、レビュー自体に影響はないのですが、 テストケースの展開はアクティブアカウントしか閲覧できないため、 アカウント数を最小で運用しようとすると課題になってしまいます。 現状は、非アクティブユーザーとアクティブユーザーを切り替えることで、 プロジェクト側のステークホルダーにはテストケースを共有しています。 もし費用面で制限がないのであれば、 各プロダクトの企画及び開発リーダーの2名+αとして人数に余裕のあるプラン選択にすることをお勧めします。 来年度は効果測定を実施しつつアカウントを増やし、 運用面でどのような変化が起き、開発側の反応はどうだったのかは別の機会にお伝えできたらと考えています。 6. 入力工数の活用(上手くいっていない点、課題) Testrailでは各項目実施時に工数を記録できる機能がありますが、現状はまだ活用できていません。 将来的にはテスト計画時の見積もりに活用したいと考えてはいます。 7. 自動化ツールとの連携が出来ていない(上手くいっていない点、課題) 例えば、現在モバイルプロジェクトでは毎日夜間にスモークテスト(荒めの全体動作確認)を実行しています。 理想像としては、どのrevison番号で実行してどういう結果だったかを、自動的にテスト管理ツール側に出力できるようにしたいのですが、 技術力と知見が足りず悪戦苦闘中です。 5. まとめ 導入してからの上手くいっている点、どちらかというと上手くいっている点、及び課題を簡単ではありますがまとめてみました。 正直、TestRailというツールの機能がリッチすぎて触れていない・活用できていない点が多くあり、 恥を忍んでブログを記載しています(´;ω;`) 運用ルールも、まだプロダクトごとに差分があるような導入の初期状態ですが… テスト管理ツールを導入してみた結論及び感想としては、 テスト管理に関する工数削減など、テストマネージャーといわれる職域の方の効率化の面で貢献してくれる可能性は十分にあると思います。 しかしながら、ある程度テストプロセスが成熟しているプロダクトでは、 導入時のコストを鑑みると、テスト管理ツールはあまりメリットがないように導入直後は感じてしまうかもしれません。(グループへの提案時にそう感じた) そうではなく、これから開発プロセスやテストに関して固めていくんだというフェーズのプロダクトでしたら、 上手くはまると思いますので、無料のテスト管理ツールを一度触って自身の組織に提案してみるのはどうでしょうか。 提案することで、 言語化する能力や説明力、上長が求めているもの、優先度を理解できるなど、 思わぬ副産物も得ることが出来ました。 また来年、 課題に進展があった場合か新しいネタが手に入ったら、皆様にお伝えしたいなと思っています。
はじめに この記事は Safie Engineers' Blog! Advent Calendar 2023 13日目の記事です。 こんにちは。データ分析基盤グループでデータアナリストをしているワンです。 データ分析基盤グループに関しては、下記の記事で詳しい情報が掲載されています。この分野にご関心がある方は、ぜひご一読ください。 engineers.safie.link データを活用したビジネス改善とビジネスサイドとの連携強化の観点から、私たちデータ分析基盤グループはチームにおける主要KPIのモニタリングとアクションへの結び付けを促進する文化を築くことを目指しています。 セーフィーでは、データの可視化ツールとしてTableauを採用しておりますが、その利用率とデータ活用文化を向上させるために、 適切なタイミングで 適切な人々に 適切なコンテンツを 提供することを重視しています。 Tableauで構築したVizをチームメンバーが日常的に使用するSlackに自動連携させることで、データへの迅速なアクセスが可能となり、より効率的な意思決定が行えるようになり、全体としてビジネスの成果向上を期待できます。 それを実現するために、GASでTableau VizをSlackに自動配信する仕組みを実装してみました。 この記事では、Google Apps Script (GAS)を使用して、Tableau VizをSlackに自動連携する方法を紹介します。 はじめに 準備 手順 Tableau Vizのサブスクライブ TableauのログインとVizの選択 サブスクリプション機能の設定 Slack Botの作成とトークンの取得 Appの作成 Bot機能の追加とOAuthの設定 Bot Tokenの確認 APPのインストール 投稿させるSlack Botをチャンネルに招待する Google Apps Scriptの設定 GASの新規作成 GASの編集 SLACK_TOKENをプロパティに設定する GASトリガーの設定 まとめ 準備 Tableauで配信したいVizを用意します。 Tableauのアカウントが必要です。 Slackでボットを作成し、トークンを取得します。 手順 Tableau Vizのサブスクライブ 連携したいTableau Vizを選択し、サブスクライブ機能を使って、Gmailに定期配信します。 TableauのログインとVizの選択 Tableau Cloud にログインします。 Vizの選択 配信したいTableau Vizを開き、配信したいものを選びます。 サブスクリプション機能の設定 サブスクリプション機能のアクセス ビューのツールバーで、[Watch (視聴)] > [サブスクリプション] を選択します。 サブスクリプションの詳細設定 配信するメールアドレスを選びます。Tableau登録時に使用したユーザーのメールアドレスに配信したいVizを送信します。個人メールアドレスよりは、管理面や効率的に情報伝達を考えてチームグループのメールアドレスに配信するように設定します。 配信する頻度とスケジュールを選択します。今回は毎日朝08:55で指定しています。 サブスクリプションの確認 すべての詳細を確認した後、[サブスクリプション] ボタンをクリックしてサブスクリプションを完了します。 Slack Botの作成とトークンの取得 Slackボットの作成、設定、トークンの取得、インストールを手順に従って完了します。 Appの作成 Slackの公式サイトにログインした状態で、アプリケーションページ へ移動します。 [Create New App] をクリックし、[From Scratch] を選択します。 アプリに名前と対象のSlackワークスペースを指定し、[Create App] をクリックしてアプリを作成します。 Bot機能の追加とOAuthの設定 先に作成したApp のページに移動します。このページ内で、Basic Information / Building Apps for Slack / Add features and functionality で、[Bots] を選択します。 App Homeのページに移動します。こちらで [Review Scopes to Add] を選択します。 OAuth & Permissions のページに移動します。少しスクロールして、[Scope] 下の [Bot Token Scopes]で、必要なスコープを追加します。 chat:write files:write users:read users:read.email OAuth & Permissions のページで、[Redirect URLs] を追加します。 https:// /auth/add_oauth_token を追加します。 * にはワークスペースのURLが入ります。 Bot Tokenの確認 OAuth & Permissions のページで、OAuth Tokens for Your Workspaceの下で、[Bot User OAuth Token]をコピーします。 APPのインストール [Settings] から [Basic Information] を選び、TableauInsightBot AppをSlack ワークスペースにインストールします。 投稿させるSlack Botをチャンネルに招待する 作成したBotを該当チャンネルに招待します。 [Intergrations]をクリックし、[Add apps]で先ほど作成したBotを該当チャンネルに招待します。例えば仮に #daily_notification_tableauのチャンネルに招待しました。 Google Apps Scriptの設定 GASの新規作成 Google Apps Script からProjectを新規作成します。 GASの編集 作成したGASファイルに、下記コードをコピペします。例は毎日配信のスクリプトです。 function Tableau2Slack () { // スクリプトプロパティからトークンを取得 var scriptProperties = PropertiesService . getScriptProperties () ; var SLACK_TOKEN = scriptProperties . getProperty ( 'SLACK_TOKEN' ) ; // 今日の実行日付を取得し、東京タイムゾーンにフォーマットする var currentDate = new Date () ; var formattedCurrentDate = Utilities . formatDate ( currentDate , 'Asia/Tokyo' , 'yyyy-MM-dd\'T\'HH:mm:ss' ) ; // スクリプトプロパティから前回の実行日付を取得し、フォーマットする var lastExecutionDate = scriptProperties . getProperty ( 'lastExecutionDate' ) ; var formattedLastExecutionDate = lastExecutionDate ? new Date ( lastExecutionDate ) : null ; // 今日の実行日付が前回の実行日付と同じ場合は、関数を終了する if ( formattedLastExecutionDate && formattedCurrentDate === formattedLastExecutionDate ) { console . log ( "本日はすでに実行済みです。" ) ; return; } console . log ( "Last execution date: " + lastExecutionDate ) ; // 前回の実行日付をコンソールに出力する // Tableauからの自動メール取得(条件に一致する最新のメールを一件取得) var Threads = GmailApp . search ( 'from:"[メールアドレス]" subject:"[メールタイトル]"' , 0 , 1 ) ; var messages = Threads [ 0 ] . getMessages () ; var message = messages [ messages . length - 1 ] ; // 自動メールから画像と日付を取得 var attachments = message . getAttachments () ; var date = new Date () ; date . setDate ( date . getDate () - 1 ) ; // 現在の日付から1日前の日付を取得 var time = Utilities . formatDate ( date , 'Asia/Tokyo' , 'yyyy年M月d日' ) ; // Slack API Bot設定 var data = { 'token' : SLACK_TOKEN , 'file' : attachments [ 0 ] , 'filename' : '[ファイル名]' , 'channels' : '[配信するチャンネル名]' , 'title' : time + '[Tableau Viz名]' , 'initial_comment' : '[コメント]' } ; var option = { 'method' : 'POST' , 'payload' : data } ; UrlFetchApp . fetch ( 'https://slack.com/api/files.upload' , option ) ; // スクリプトプロパティに今日の実行日付を保存する(日付と時刻を含む形式) scriptProperties . setProperty ( 'lastExecutionDate' , formattedCurrentDate ) ; } ; コードの下記の情報は適切な値に置き換える必要があります。 [メールアドレス] [メールタイトル]  [ファイル名] [Tableau Viz名] [配信するチャンネル名] [コメント] SLACK_TOKENをプロパティに設定する プロジェクトのプロパティ設定 GASメニューバーから歯車アイコンの[プロジェクトの設定]をクリックします。 [プロジェクトの設定]画面の一番下に[スクリプト プロパティ]があります。 SLACK_TOKENの追加 [プロパティ]フィールドにSLACK_TOKENと入力します。 [値]フィールドにSlackのトークン値を入力します。このトークンはSlack APIから取得したものを使用します。 入力した情報を確認し、「保存」ボタンをクリックします。 今回はスクリプト内でこのプロパティを使用しているので、 PropertiesService.getScriptProperties().getProperty('SLACK_TOKEN') を使用してアクセスします。 GASトリガーの設定 この手順に従って、GASで定期的にスクリプトを実行するトリガーを設定することができます。これにより、例えば毎日特定の時刻にデータを処理したり、定期的なTableauのVizを送信したりする自動化が可能になります。 GASのメニューバーから時計マークのアイコン[トリガー]を選択します。これにより、[現在のプロジェクトのトリガー]画面が開きます。 右下にある「トリガーを追加」ボタンをクリックします。 この画面でトリガーを設定します。 実行する関数を選択します。 今回の場合はTableau2Slack 実行するデプロイメントを選択します。 イベントのソースとして時間主導型を選択します。 頻度の設定 [日単位] [週単位]など、スクリプトの実行頻度を選択します。 さらに詳細な時間設定(毎日の特定の時間帯、週の特定の日など)を行います。 設定が完了したら、[保存] ボタンをクリックしてトリガーを保存します。 まとめ この記事では、GASを活用してTableau VizをSlackに自動連携する方法を紹介しました。SlackへのTableau Vizの自動連携が、私たちの業務スタイルに新たな風を吹き込んでいると感じています。 Tableauには既にサブスクリプション機能が備わっており、定期的にメールでのViz配信が可能です。しかし、これらはメールボックスに届くため、日々の業務の中で見落とされがちです。 Slackに連携されるTableau Vizは、日々のコミュニケーションの流れの中で自然に目に触れることが多く、必要な情報をすぐに手に入れられます。これにより、ただのオンライン上にある数字やグラフではなく、「話す」データを共有して、よりダイナミックな議論が生まれ、具体的な行動につながりやすくなります。 たとえば、KPIを示すTableau VizがSlackに投稿されると、そのスレッド内での議論で、その数値をめぐって即座に議論が始まり、必要なアクションが迅速に決定されます。これは、メールで配信されるデータではなかなか起こり得ないことだと思います。 Slackの使い勝手の良さから、データへのアクセスがより手軽で直感的になり、データ利用やTableau利用のハードルが大きく下がることが期待できます。
「この記事は Safie Engineers' Blog! Advent Calendar 8日目の記事です」 自己紹介と本日のテーマ セーフィー株式会社 開発本部 エンジニアリングオフィスの武田 智一です。 セーフィーには2023年1月に入社して、エンジニアに対する組織開発全般をおこなっています。エンジニアリングオフィス(組織開発)って何やっているの?というのはまた別の機会でお話しするとして、 今回はセーフィーのエンジニア全員が参加する 「開発本部会のやり方変えてみた」 のお話しをさせてもらえればと思います。 自己紹介と本日のテーマ 全体会議の課題 会議体の再定義 1. なぜやるのかを言語化 2. どうやって体感するか、の定義 3. アジェンダの再設定 改善ステップ(ストーリー作り) 改善ステップ 結果 まとめと今後の予定 全体会議の課題 現在セーフィーの開発本部には約90人のエンジニアが在籍しています。 この90人全員参加のオンライン開発本部会を月1回1時間実施しています。 「この90時間ははたして有効に使えているのか?」 と、エンジニアの皆さんならとっても気になりますよね。 セーフィーでも同じ状況でした。 具体的には開発本部会には以下のような課題がありました。 一方的な情報ダウンロードの会になっている 共有される情報が人によっては既知の情報だった 共有される情報が人によっては自分のやっていることとは遠い情報のため実感がわかなかった 結果として参加率も低く、全体的に効果的で効率的な会議運営ではなかった こういった課題を解決するために、今年の2月からエンジニアリングオフィスが主管となり会議体運営を見直しました。 会議体の再定義 基本的に、変更前後も会議の目的自体は変わっていません。 ただ、WhyをベースにHowを明確にしアジェンダを組みなおしました。 具体的には以下のように再設計しました。 1. なぜやるのかを言語化 セーフィーのビジョンは「映像から未来をつくる」です。そして、私たち開発本部は映像から未来をつくるを実際に体現しているエンジニア組織(創る組織)です。自分たち自身の業務やアウトプットは必ずビジョンにつながっているはず。 ただ、エンジニアの人数も多くなり、部署やグループも増えた結果、そのつながりをなかなか体感しづらい。 そこで、この開発本部会を軸に月に1度改めて自分たちがビジョン実現に貢献していることを認知する。そういう場にしたいという思いから、開催理由(なぜ)を「映像から未来をつくる」を体感するためにしました。 2. どうやって体感するか、の定義 ビジョン実現を体験するには何が必要かを考えたとき、まさに組織開発でするべきことだと整理しました。 組織開発において必要になってくるのは、同じ目標を正しく理解して、現在地を知ることから始まります。また、現在地を知った上で、どう感じているかを共有することで、お互いのことを深く知り、さらに一体感が生まれます。そういったHOWの部分を方針として明確化しました。 3. アジェンダの再設定 この方針をもとに、ベースとなるアジェンダを以下のように組みなおしました。 人により文章は捉え方が変わりますが、数値は同じです。 そこで開発本部全体をあらわす数字(数字で見る開発本部)を定義して、その数字を毎月共有することで、まずは目線をそろえるようにしました。 その数字の変化を具体的な報告で説明することで、全体から具体へのブレークダウンをしやすくしています。 参考までに、10月の開発本部会のアジェンダと数値報告の例です。 改善ステップ(ストーリー作り) アジェンダの整理までは良いですが、それだけでは会議運営の改善にはつながりません。 毎月1回=年12回の会議を連携して有効に使うために、それぞれの月でどういった状態になってほしいか、その結果全体としてどう流れを作るかを最初に設計しました。 改善ステップ 月 テーマ 狙い やること 1月 現状確認 ー 昨年と同じ形で開催 2月 認知 本部会で何を実現したいかを理解してもらう 概要説明、アンケート設計 3月 気付き ちょっと変わったかもという雰囲気をつくる 数字で見るシリーズの意味付、アンケートフィードバック 4月 自分事化 組織戦略(中身)について理解してもらう ロードマップに沿った組織戦略の発表 5月 事を知る1 各部でやっていることを知る 各部毎の発表(プロダクト詳細発表) 6月 事を知る2 各部でやっていることを理解したうえでフィードバックできる状況をつくる ガヤスレの活用、各部勉強会とのリンク作り(誘導) 7月 下期計画発表 上期の結果及び下期の目標共有 上期ふりかえり、下期注力目標 8月 人を知る1 組織にどんな人がどんな思いで働いているかを知る(人にも興味を持ってもらう) CTO発表 9月 人を知る2 他部署のことも知る 企画本部発表、部室長発表 10月 人を知る3 他部署のことも知る 営業本部発表、部室長発表 11月 全体を知る 他からどう見えているか(どう変わったか)知る CS本部発表、部室長発表 12月 年度ふりかえり 来年に向けた組織戦略を理解する 来期組織戦略発表、来期組織枠の説明 実際にはこの通りには進みませんでした。 ただ、各月毎の狙いが実現できたかを、アンケート結果等から毎回評価をおこないました。その結果を踏まえて微調整をしながら、翌月以降の個別アジェンダを整えることで、大きくストーリーを変更することなく、会議体運営の改善につなげることが出来たと思います。 結果 アンケートの結果です。 会議の満足度を100点満点として、何点だったかを毎回聞いています。 その結果、平均満足度は90点にまで上昇しました。また、参加率も大きく向上し10月の参加者数は100名を突破しました。(別部署の人も参加しているため、開発本部全員の人数よりも多くなった) 自由記述のアンケートコメントを見ても、毎月の開発本部会を楽しみにしてくれる人も増えてきたという実感があります。 まとめと今後の予定 開発本部会はみんなの満足度を上げることが目的ではありません。 映像から未来をつくる道筋を理解し、現在地を知ることでお互いが誇りをもってプロダクトを成長させ続ける。そして、開発文化を成熟させた最高の開発チームで「映像から未来をつくる」を実現することがゴールです。 そのためには足りていない部分はたくさんあります。また、組織も人もどんどん成長しています。 そういう変化も想定したうえで適切にハンドリングして、これからも開発本部全体会議を軸に情報を皆に届けられればと思っています。 なお、来年は以下のことにもチャレンジする予定です。 開発本部を表す数値のアップデート(と本部外への展開) 開発本部会以外の会議体設計との連携、ストーリー見直し ガヤ(フィードバック)の活性化 最後に、会議を変えるだけでは組織は変わりません。 ただ、変化のきっかけづくりにはなったと思います。これからもエンジニアリングオフィスとして、エンジニアみんなが生き生きと働ける環境づくりに貢献していければと思います。 最後まで読んでいただきありがとうございました!
はじめに こんにちは!Safie QAグループ(QCDグループ)のグループリーダーの山谷です。 前回はテストの業務についてのテックブログ を公開しましたが、今回はなりたちについてのお話になります。 私自身はSafieに入社するまではQAエンジニアどころかテストエンジニアとしてもキャリアがない状態で入社してます。 もし同じ状況でQAエンジニアチームを作る人達の何かの参考になれば嬉しいなと思い、ブログを書くことにしました。 テスト体制を作ろう テスト担当者を作ろう ■改善活動その1 ~顧客対応を巻き取る~ ■改善活動その2 ~バグチケットを溜める~ テストチームを作ろう まとめ テスト体制を作ろう 当時のSafieは開発メンバーがテストをほとんど実施している環境でした。 2020年はそんな状況で「QAについて何もスキルセットがない状態で入社した人間がテストチームをまずは作ることにした」年になります。 私の入社時期はちょうどモバイルアプリのリニューアルと、 SafieManager のリリースが控えておりました。 私の上司はこれらのテストを担当してくれそうな人を探していたのですが、とりあえずモバイルのテスト担当者から作ることにします。 そう、私です。 テストの項目書のひな形を渡され、こう書くんだよとナレッジ(もちろん外部サイト)のURLと開発メンバーのMTGに放り出されました。 ここから私のQAエンジニアとしてのキャリアが始まりました。 テスト担当者を作ろう サービス開発黎明期あるあるな話ですが、当時のSafieは仕様書がないものがほとんどでした。 そのため、まずはアプリでできることを書き出します。 Safieモバイルアプリの場合には ・ログイン画面 ・カメラ一覧  ・各種ボタン ・ストリーミング画面  ・デバイス設定  ・その他機能ボタン みたいな感じですね。 テスト版のアプリを使い画面と、それに設置されている各パーツについて期待動作を洗い出し、開発と期待結果とそれを導くための手順を埋めていきます。 当然ながらこの当時のテストケースはものすごく粗く、テストをしながらテスト項目を増やしたり、テスト手順、期待結果の書き換えなどもすごく多く発生します。 リリースまでにはこぎつけましたが、動作の安定性については今一つ。 今後も継続して品質改善を行うにあたっての行動に移ることになります。 ■改善活動その1 ~顧客対応を巻き取る~ リリース後しばらくはモバイルアプリの顧客サポートは基本的には私が巻き取ることにしました。(なりました。) エンドユーザーから指摘されたバグを迅速に開発に連携を行える テストケースの抜け漏れに気づくことができる 自分の対応のノウハウを他カスタマーサポートメンバーに共有ができるようになる お客様から温度感が高いご意見をいただくなど大変ではありましたが、開発メンバー内外含めてメリットはありました。 何より黎明期っぽい働き方ができたので楽しかった面もあります。 また、当時はモバイルアプリとしての不具合対応フローやノウハウがカスタマーサポート部にはあまりなかったので、そういった運用を作ったりしたのも良い思い出です。 ■改善活動その2 ~バグチケットを溜める~ 当たり前ですがその当たり前が当時はありませんでした。 バグチケットを置き場所を決めて、バグの修正プロセスを開発と話し合いリリーススケジュールを決める 改善を確認した際のチケットクローズまでのフローを立てる チケットを積み残す際の基準を作る バグチケットを参考にリグレッションテスト項目を作る など、今では当たり前にやっている運用をまずは作ることからスタートしてます。 こうしてまずはモバイルアプリにテスト担当者が一人出来上がることになりました。 テストチームを作ろう さて、モバイルがひと段落つくと次はSafieManagerのリリースがやってきます。 SafieManagerは開発メンバーがテストケースを作成し、私はテスト担当としてプロジェクトに組み込まれました。 SafieManagerはSafieのWebアプリケーションの中ではかなりシステムが複雑であったため、テストケースもモバイルに比べると倍以上ありました。 開発側もテスト実施にお付き合いいただけることになったのですが、さらに元QAエンジニアでSafieViewerのテストを実施されていた社員1名がアサインされます。 だいたいこの辺りからテストをやってくれる人達として認知されていくようになっていきます。 併せて全プロダクトへのテスト参加を目指して人員の拡大を進めていくことなり、僕+社員1名、業務委託1名~2名でQAチームとして業務に取り組むことになります。 また、テストのことを少しでも学ぼうとJSTQBを取得したのもこのあたりだった気がします。 当時のなんとなくの役割 全PJの要件定義の調整+テストの全体スケジュールの調整+テスト作成+テスト実施 山谷 Safie Viewerや、山谷が持ちきれないもののテストプロセス管理および実施 社員 テスト実施のサポート 業務委託 さて、上のような体制で半年ほど立つと、1つの課題が生まれてきました。 気づくと毎週私のMTG時間が30時間を超えています。 社内PJ全てに参画した結果、1週間の予定がほぼMTGで埋まってしまうことになりました。 頼っていただけるのは嬉しい反面テスト作成や、実施などはMTG中に内職をするか残業がマストになってます。 この課題を解決するにあたり、要件定義から入れるエンジニアを増やすことにします。 採用基準の中にプロダクトの品質や開発プロセス改善に取り組んだことがある、もしくは取り組みたいと考える方を追加し、こちらからの面接の内容もそれに則った内容に変更しました。 1年くらい上記で採用を続けた結果の所感ですが、以下のようなことを感じてます。 QAエンジニアはかなりジョブ定義が曖昧な職である ほとんどの場合はテストエンジニアやテストマネージャーといった経歴の方が多い ビジネス、企画、運用などを包括的な目線をもってプロセス改善に取り組んでいただけるか否かは当人の意識や資質に依存しやすく、こういった経験を持っている方は非常に少ない また、上記のようなスキルを持った方であっても芽が出るまでにはある程度の期間が必要 といった部分です。 そのため、最近では品質改善をどのように改善してきたか、もしくは課題をお伝えしたうえでそれをどのように改善したいと考えるか、などの質問を増やし社内でご活躍いただけるか否かの解像度をあげるように取り組んでいます。 まとめ まとめに入っていきますが、現在は社員6名、業務委託5名の11名となり、グループとなるまで拡大することができましたが、来年度は15名程度までは拡大したいと考えます。 Safie のQAグループのいいところはプロダクトの魅力と、裁量の広さです。 「良い品質のアプリケーションを作るだけではなく、良いサービス/プロダクトを作っていく」ことに共感をいただけましたら、ぜひ応募をいただければ嬉しいです。 最後までお読みいただきありがとうございました。
この記事は Safie Engineers' Blog! Advent Calendar 2023 4日目の記事です。 はじめに システム概要 システム構成 Stable Diffusion ChatGPT FastAPI Poetry 実装 プロジェクトの作成 ファイル一覧API API作成 URLのパスでディレクトリを指定できるように修正 ファイルのダウンロード対応 ファイル一覧ページ 画像のメタデータ取得 画像一覧ページ 画像のメタデータの表示 まとめ はじめに こんにちは、開発本部の中村俊成です。 今年も色々と流行りの技術がありましたね。その中でも生成AIは注目度が高かったと思います。私も生成AIの社内活用を検討する過程で、業務や個人的なプロジェクトにおいてChatGPTやGitHub Copilotなどの生成AIを徐々に取り入れています。 そうした中、Stable Diffusionで生成した画像とプロンプトを一緒に表示できるツールが欲しくなり、ChatGPT(GPT-4)の助けを借りて簡単なものを作成しました。また、セーフィーのサービスの一部で使用しているFastAPIフレームワークの基礎を学ぶ良い機会でもあったので、このツールの開発にFastAPIを使用しました。 この記事では、その開発過程を紹介します。 以下のような方の参考になれば幸いです。 何かを作りたい、または新しい技術に触れたいと思っているが、なかなか始められない方 私のことですmm ChatGPTの使用例を探している方 シンプルな指示を使った例になりますので、プロンプトエンジニアリングのサンプルとしては物足りないかもしれません FastAPIを使用したシンプルなサーバーの実装例に興味がある方 ここで紹介するのは実験的な実装ですので、参考にされる場合は注意してください システム概要 PC上で、Stable Diffusionで生成した画像を、画像サーバーに保存しておき、スマホや他のPCから閲覧できるようにします。画像サーバーの実装は、ChatGPTに相談しながら行いました。 システム構成 システム構成 Stable Diffusion Stable Diffusion は、Stability AI 社が開発している、ユーザーが与えた指示(prompt)を元に画像を生成するAIモデルです。 Stable Diffusion で画像を生成するためのツールとしては、 stable-diffusion-webui を利用しました。 stable-diffusion-webui で生成した画像には、生成時の prompt がメタデータとして記録されています。 ChatGPT ChatGPT は、Open AI社が開発している、人工知能に基づいたチャットボットで、テキストによる会話ができます。ユーザーのリクエストに応じて、情報を提供したり、創造的な内容を生成することが可能です。ブラウザや専用のアプリケーション、APIを通じて利用可能です。 FastAPI FastAPI は、Pythonの標準である型ヒントに基づいてPython 3.6 以降でAPI を構築するための、モダンで、高速(高パフォーマンス)な、Web フレームワークです。 Poetry Poetry はPythonのパッケージ管理ツールの一つです。pyproject.toml ファイルを使用してプロジェクトの依存関係を管理します。 実装 実装したコードは こちら から確認できます。 では、実装の過程を紹介していきます。 プロジェクトの作成 まずはプロジェクトの作成をChatGPTにお願いしてみます。 プロジェクトの作成 指示に従って、作業を行いました。 サーバーが起動し、ブラウザで開けるようになりました。 Hello World ファイル一覧API API作成 最低限の機能として、画像ファイルの一覧が必要だと考えました。 ファイル一覧API作成 URLのパスでディレクトリを指定できるように修正 それっぽいコードが出力されましたが、ディレクトリが指定できなさそうに見えます。修正を依頼しました。 ファイル一覧APIの修正 これでコード上のBASE_DIRECTORYとURLのパスでディレクトリを指定できるようになりました。BASE_DIRECTORYにプロジェクトのディレクトリ以下にある static ディレクトリを指定して、サーバーを起動してみると、ファイル一覧が取れました。 パス レスポンス /files/ ["/Users/t-nakamura/Study/src/image-server/static/.gitkeep"] ファイルのダウンロード対応 ファイル一覧に表示されたファイルのダウンロードに対応しようと考えました。 ChatGPTが提示するコードを見ながら、以下のような要望を出して、試行錯誤を行いました。 subdirectory_name に ../ のような相対パスの指定がされたら無視するようにしたいです。 APIで返すファイル名は、BASE_DIRECTORYからの相対Pathにしたいです APIが返すレスポンスを以下のようにして、ディレクトリのリストも返したいです。 {"files": ["file1", "file2"], "dirs": ["dir1", "dir2"]} /files/{subdirectory:path} APIで返したファイル名を指定したら、そのファイルをダウンロードできるようにしたいです。 /files/{subdirectory:path} と /download/{filepath:path} を統合して、指定したpathが、ディレクトリだったら、ファイル一覧を返して、ファイルだったらファイルをダウンロードできるようにしたいです。 ファイルが画像の場合だけ、ファイル一覧で返したり、ダウンロードできたりするようにしたいです。 あいまいな表現が含まれていますが、ChatGPTが適切に解釈して、最終的に以下のようなコードを出力してくれました。 ディレクトリ内のファイル一覧表示と、ファイルのダウンロード対応 サーバーの実装に反映させ、以下のようにJSONを返せるようになりました。また、画像ファイルをのパスを指定するURLを開いた場合は、ブラウザ上で画像を表示できるようになりました。 パス レスポンス /files/ {"files":[],"dirs":["2023-11-29"]} /files/2023-11-29 {"files":["2023-11-29/2023-11-29 10.02.37.png"],"dirs":[]} ファイル一覧ページ JSONで返すと、ディレクトリやファイルをブラウザ上で選択して開くことができません。そこで、簡易的なHTMLでファイル一覧ページを返すようにしようと考えました。 ファイル一覧ページの実装方針 ChatGPTからの返答が長かったので、上記のスクリーンショットでは割愛しましたが、サーバーのコード修正や、テンプレートファイルの内容が提示されました。提示された実装例に従って、HTMLを返せるようになりました。( 対応時のコミット ) パス スクリーンショット /files/ /files/2023-11-29 /files/2023-11-29/img.png 画像のメタデータ取得 ここで、画像のメタデータを取得する方法について確認しておくことにしました。 メタデータ取得APIの実装 Pillowライブラリを使えばできそうなことが分かりました。ライブラリをプロジェクトに追加し、提示されたコードで metadata 取得APIを実装すると、メタデータを取得できるようになりました。 パス スクリーンショット /metadata/img.png 画像一覧ページ データ取得に関しては、要素が揃ったので、表示部分の実装を行うことにしました。一覧性を高くするために、グリッド上に画像を表示することにしました。サーバーの実装と切り離して、シンプルな実装を知りたいと考えて、これまでとコンテキストを変えるため、新しいチャットを始めました。 画像一覧ページ 提示されたコードを、テンプレートの file_list.html に反映すると、画像がグリッド状に表示されるようになりました。 パス スクリーンショット /files/2023-11-29 画像のメタデータの表示 画像のメタデータを表示できるようにします。画像の下に表示する方式も試したのですが、画像の一覧性が下がるため不採用にしました。画像の右下にボタンを配置して、ボタンをクリックすると、モーダルでメタデータを表示できるようにしました。 メタデータのモーダル表示 提示されたHTML、CSS、JavaScriptのコードを、少し調整して、テンプレートの file_list.html に反映すると、意図通り動作するようになりました。( 対応時のコミット ) 完成版 まとめ ChatGPTにざっくりとした指示を出すだけで、動くものがすぐに仕上がるのは、驚きでした。動くものがあることで、機能を即座に試すことができますし、次に「ここをこうしたい」といったアイディアが浮かび、徐々に自分の理想に近づける原動力となりました。その結果、「あれば便利だろうな」と漠然と考えていたものを、実用的な形で素早く作成できました。 業務においても、社内外向けサービスのプロトタイプを作成する際などに活用できるという実感が得られました。今後も、この実感を基に、生成AIを生産性の向上や、新しい価値の創出に活かしていきたいです。
この記事は Safie Engineers' Blog! Advent Calendar 2日目の記事です。 セーフィー株式会社でテックリードをやっております鈴木敦志です。 セーフィーはクラウドカメラのSaaSを提供しており、現在22万台程度のデバイスに対してカメラ映像をクラウドから視聴する機能を提供しています。 それに加えエンタープライズ向けの権限管理機能や社内向けの販売管理ツールなど複数のサービスを運営しており、各サービスでMySQLのDBを共有しているためDBのテーブル数が肥大化し構造がわかりにくくなり、新機能開発の妨げとなっていました。 本稿ではデータベースのドキュメンテーションツールである tbls を導入し、DBスキーマ管理ツール skeema 、ドキュメント生成ツール mkdocs 、Github Actionsなどと組み合わせてスキーマ管理からドキュメント生成までをやっていきます。 現在の問題点 ドキュメント記述方法の検討 - tbls ドキュメント生成手順 skeema によるDBスキーマの適用 tbls によるドキュメント生成 mkdocsによるHTML生成 ドキュメント配信 tblsのViewPoints機能によるドキュメントの改善 今後の課題 .tbls.yml のエディタ補完 現在の問題点 セーフィーでは主にDBにAurora MySQLを利用しており、現在のテーブルはシャーディング用途のものを除くと452、すべて含めると5,718個あります。 各テーブルにはコメントや外部キー制約がなく、テーブルの用途を把握するにはプログラムコード内のSQLをすべて調べる必要がありました。 この問題の解決策として別途DBとコードの分割を行っており、並行してDBのドキュメント記述の仕組みの整備を行っていきます。 ドキュメント記述方法の検討 - tbls ドキュメントの記述方法は以下の方針で検討しました。 テーブル定義からドキュメントを生成する 上記に加え別途テーブル/カラムに対するコメントや外部キー制約を記述できる テーブル定義 (今回はGithubで管理されたSQLファイル) と近い場所でドキュメントを管理できる ドキュメントをCIで自動生成する これらの要件を満たすツールとして SkeemaSpy などを検討し、CIとの親和性やyamlによる書きやすいDBメタデータ記述などを決め手に tbls を選択しました。tblsはMarkdownでドキュメントを出力するためHTMLページに変換する必要がありましたが、それには mkdocs を利用することにしました。 下図が出力例です。(サンプルのデータベースを使用しています) tbls + mkdocs出力例 ER図には外部キー制約またはtbls設定ファイル (.tbls.yml) に記載されたリレーションが表示されます。 tbls + mkdocs出力例 (ER図) ドキュメント生成手順 skeema によるDBスキーマの適用 セーフィーではDBスキーマを CREATE TABLE 文の記載されたSQLファイルの形式で記述し、skeema ( https://www.skeema.io/ ) で管理しています。 ドキュメント生成のワークフローではローカルまたはGithub Actions上で起動したMySQLサーバーに対してスキーマを適用します。 tbls によるドキュメント生成 先述した tbls ( https://github.com/k1LoW/tbls ) ではMySQLデータベースおよび設定ファイル (.tbls.yml) をもとにMarkdownドキュメントおよび図表を出力します。 DBドキュメントを記述する際には簡単な内容であればMySQLのテーブル/カラムコメントを追記、Markdownで記述が必要なような複雑な内容であれば設定ファイルに説明を記述しています。 mkdocsによるHTML生成 mkdocs ( https://www.mkdocs.org/ ) はpythonで実装されたMarkdownファイルからHTMLドキュメントを生成するソフトウェアです。 様々なテーマや拡張機能が用意されていて、今回は下記の構成をとりました。 mkdocs-material: 高機能なテーマ シンタックスハイライト ( https://squidfunk.github.io/mkdocs-material/reference/code-blocks/ ) mermaid.js統合 ( https://squidfunk.github.io/mkdocs-material/reference/diagrams/ ) glightbox: 画像拡大プラグイン。関連の数によってはER図が大きくなるため採用 現在下記 mkdocs.yml を使用しています。 site_name : "Northwindデータベース定義" theme : "material" plugins : - "search" - "glightbox" extra_css : - "stylesheets/extra.css" markdown_extensions : - pymdownx.highlight : anchor_linenums : true line_spans : __span pygments_lang_class : true - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.superfences : custom_fences : - name : mermaid class : mermaid format : !!python/name:pymdownx.superfences.fence_code_format ドキュメント配信 生成されたHTMLドキュメントをAWS S3にアップロードし、Google WorkspaceのOpenID Connect認証をかけて配信しています。 tblsのViewPoints機能によるドキュメントの改善 tblsのテーブルコメントおよびカラムコメントだけでも一定の役にたちますが、そもそものテーブル数が多いため探しているテーブルを見つけるのが難しいという問題があります。 これに対してtblsにViewPointsという機能が実装され、ある関心ごとにテーブルをグルーピングしドキュメントを構成することができるようになりました。これにより「契約情報」「カメラ設定」などの関心ごとにテーブルの概観と関連を把握することができ、全体感を把握することが容易になりました。 ViewPointsは .tbls.yml に下記のように記述します。 viewpoints : - name : "商品情報" desc : | 各商品は `Products` テーブルで管理され、関連するカテゴリ情報 `Categories` とサプライヤ情報 `Suppliers` の情報を持ちます。 tables : - "Products" - "Categories" - "Suppliers" tbls + mkdocs出力例 (ViewPoints) 今後の課題 上記の実装によりデータベースドキュメントの生成に対応しました。現状はコメントが付与されているテーブルはごく一部であり、今後はテーブルのコメントを充実させていく必要があります。 .tbls.yml のエディタ補完 .tbls.yml にデータベースのドキュメントを記述していく方針ですと、フィールド名やcardinalityの値などでエディタの自動補完が効くと便利です。 現状エディタ拡張などはないので、ひとまずVSCodeの YAML Language Server とtblsのソースコードから生成したJSON Schema ( https://gist.githubusercontent.com/suzuki-safie/2b56ab4771134d3c801dcd497677f53d/raw/tbls-config.schema.json ) を利用することである程度の補完とバリデーションを実現しました。 利用するには YAML Language Serverの導入後、以下の設定をVSCodeの設定に追加してください。 { // ... "yaml.schemas" : { "https://gist.githubusercontent.com/suzuki-safie/2b56ab4771134d3c801dcd497677f53d/raw/tbls-config.schema.json" : [ ".tbls.yml" ] } }
この記事は Safie Engineers' Blog! Advent Calendar 1日目の記事です。 こんにちは。セーフィー株式会社でバックエンドエンジニアをしている河津です。 アドベントカレンダーついに始まりましたね。初日の記事なので少し緊張します。 今年も様々な領域の記事がたくさん公開されると思いますので、是非他の記事も楽しみにしてくださいませ。 さて今回は、WebSocketを用いているサーバ側のアプリケーションの動作確認にwscatというツールが便利だったよという話をします。 背景 wscatとは 動作確認してみる 最後に 背景 セーフィーにはカメラの映像を視聴することができるSafie Viewerというプロダクトがあります。(デモ画面は こちら 。) このプロダクトの中で、映像のサムネイルを数秒おきに更新している箇所があり、更新の手法としてWebSocketでの通信を用いています。 具体的には、サーバ側で数秒間隔でカメラの映像からサムネイルを作成し、サムネイル画像のバイナリをWebSocketでクライアント側に送信します。 クライアント側としては都度新しいサムネイルをリクエストする必要が無いようになっています。 この仕組み周りに修正を入れた時に、WebSocket周りの動作確認を行うために良い方法を調べたところ、wscatというツールを知りました。 wscatとは wscat とはWebScoketのサーバを立ち上げたり、クライアントとして利用することができるツールです。 Node.jsが入っていれば npm コマンドでインストールすることができます。 $ npm install -g wscat 試しにサーバを立ち上げ、クライアントから通信を行ってみましょう。サーバを立ち上げるには以下のコマンドを実行します。(今回はポート3000で立ち上げてみます。) $ wscat -l 3000 -l オプションをつけると、指定したポートでWebSocketを受け付けることができるようになり、サーバーの役割を果たします。 クライアント側からの通信は以下のコマンドで行います。 $ wscat -c ws://localhost:3000 # ws://を省略しても繋がります。 $ wscat -c localhost:3000 # TLSを使った通信であればwss://と明示的に指定します。 $ wscat -c wss://example.com:443 -c オプションの後に接続したいサーバのエンドポイントを指定することで、サーバと接続されます。 それぞれ別のターミナルから実行すると、ポート3000でハンドシェイクされ、サーバ・クライアント間でメッセージを送り合うことができます。 動作確認してみる サーバ側で実装したWebSocketのエンドポイントを指定して動作確認を行うには、上記例のうちクライアント側からの通信を行う -c オプションを使用します。 リクエストヘッダを -H オプションで指定できるので、WebSocketの通信に使用する Sec-WebSocket-Key 、 Sec-WebSocket-Version などのヘッダ情報や、Authorizationヘッダによる認証情報の送信、Cookieの送信なども可能です。 この辺りの使い方はcurlに近く、個人的にかなり使いやすく感じています。 TLS利用、Bearer認証を行う前提とすると、実行サンプルとしては以下のような形になります。 $ wscat -c wss://{WebSocketエンドポイント} \ -H 'Sec-WebSocket-Key: {任意の値}' \ -H 'Sec-WebSocket-Version: {執筆時点では13}' \ -H 'Authorization: Bearer {アクセストークンなど}' 最後に 本記事では触れませんでしたが、逆にクライアント側でWebSocketを用いた実装を進めている際に、サーバ側の開発を待たずに -l コマンドで立てたサーバと疎通しながら実装を進めることもできそうですね。 WebSocketを使ったアプリケーション開発を行っている方は、ぜひ参考にしていただけると幸いです。
こんにちは。フロントエンドエンジニアの江守です。 映像閲覧WebアプリであるSafie Viewer(以下Viewer)の開発をしています。 本記事では2023年6月に「 Safie Pocketシリーズ 」で利用可能となった遠隔臨場モードについて紹介したいと思います。 遠隔臨場モード機能とは 対応の背景 グループコーディング まとめ 遠隔臨場モード機能とは 遠隔臨場モード機能とは、「遠隔臨場」での実施記録撮影時に、監督員などのワイプ映像をキャプチャ内に含めた保存ができる機能となります。 具体的には、下記手順にて有効となり、スクリーンショットで撮影いただくことで実施記録として保存することができます。 デバイス設定の設定画面で、「遠隔臨場モード」をONにします。 Viewerの音声通話を実行し、カメラのON/OFFボタンをONにするとViewer画面上にワイプ映像を表示します。 対応の背景 「Safie Pocketシリーズ」を販売していく中で、いくつかの地方自治体では以下のような独自要件があり、導入が難しいケースがあることが判明しました。 受注者は遠隔臨場が行われた記録として、全景と近接の映像をスクリーンショット等で撮影 記録の撮影時には必ず監督員の映像を含めて撮影 (出典: 石川県 建設現場における遠隔臨場に関する試行要領 概要版 ) 「Safie Pocketシリーズ」を使いながら遠隔臨場を行う際は、現場サイドでは携帯しているデバイスの音声通話を使い、監督員サイドではViewerの音声通話を使うケースがほとんどかと思います。 要件1つ目については、監督員サイドで音声通話中にスクリーンショットを撮ることで問題はないのですが、要件2つ目については、監督員の映像を表示することが出来ていなかったため対応を行いました。 グループコーディング 弊社フロントエンドエンジニアチームでは、要件やデザインが固まり実装フェーズに移行、または開発がある程度進んだ段階でグループコーディングを行っています。 グループコーディングとはVisual Studio Codeの拡張機能であるLive Share機能を使って、チーム全員でコードの共同編集を行うことです。 グループコーディングを導入した経緯としては下記があります。 各メンバーの習熟度向上 ViewerはフレームワークにAngularを利用しているのですが、長く利用し続けているメンバーもいれば、入社してから初めて利用するメンバーもおり、習熟度に差があります。 習熟度の高いメンバーからアドバイスを受けることで、習熟度の向上を図ることができます。 ソースコードの品質向上 常にレビューしながら開発を進めるため、実装方法の間違いや記載ミス、おかしな変数名があったらその場で修正することができ、ソースコードの品質を向上させることができます。 本開発でもグループコーディングを行い、ビューとロジックが一緒くたとなっている箇所があったので分割したり、不必要な記載を削除することで可読性、コードの品質を向上することができました。 また、Angular 15から安定版になったStandanlone Componentsという新しい機能を採用しました。 汎用モジュールが不要となるためコードの記載量を減らすことができ、スッキリと見通しの良いコードになりました。 まとめ 建設業界では2024年4月から働き方改革によって時間外労働が厳しくなり、遠隔臨場での現場確認の必要性が増してくるのではと考えております。 Pocketシリーズを遠隔臨場でご活用していただくためにも、今後も引き続き改善を進めていきます。 また、お客様の困りごとにスピード感を持って対応するためにも、グループコーディング等の様々な取り組みを行いながらエンジニアの習熟度、ソースコードの品質向上に努めていきます。
フロントエンドエンジニアの阿部です。 2023年7月に開催されたDeveloper Boost 2023で登壇をしてきました。 Developer Boostは登壇者も聴講者も30歳以下の若手デベロッパーを対象としたカンファレンスです。 event.shoeisha.jp 初めての登壇で大きなイベントということで緊張して臨んだのですが、何事もなく終わることができてホッとしています。 今回はこの登壇について振り返っていきたいと思います。 登壇内容 スライド 内容 きっかけ 資料の作成 発表練習 本番 今回のイベントに参加してみて 登壇内容 スライド 内容 未経験からエンジニアになった経験を元に今までどのようなキャリアを歩んできたのか、またその中で感じた悩み、今後のキャリアプランまで赤裸々に語りました。 最も伝えたかったことは以下になります。 今まで3社経験してきて結局どんな会社にいても悩みが消えることはないと感じました。なので、 悩みを深く考えすぎずに日々エンジニアとして成長していくことが、結局のところ最も大切なことであるということです。 この考えに至った経緯など詳細は以下の記事を覗いてみてください。 codezine.jp きっかけ 「こんなイベントがあるんだけど登壇してみない?」と上司の方からお話を頂き、自分からだとなかなか登壇しようとならないし、いい機会だからやってみようということで勢いでこの話を受けました。 資料の作成 キャリアよりのイベントということでキャリアについて30分話すことになりました。 「30分も何話そう...」と悩みましたが自分が話せるのは「未経験からエンジニアになった経験」だと思ったのでこの内容で発表することを決めました。 試行錯誤しながらなんとかスライドを作り上げました。 発表練習 時間を測りながら1人で黙々と喋るという練習を行ったり、 社内リハーサルとしてイベントの企画の方々の前で発表練習をしたり、色々と練習しました。 リハーサルで出た課題を修正しつつ、本番までの準備を整えました。 本番 話し始めたら意外に緊張せず、多少は上手く話せたのかなと感じています。 同じ悩みを抱えた同年代の若手エンジニアが質問ブースに何人か足を運んでくださり、「こんな時どうしてました?」「どうやって悩み解決していました?」など色々と質問を頂きました。 特に「他人と比較してしまうことに悩んでいます。」という悩みを持っている方が多い印象でした。 他人との比較ではなく、過去の自分と現在の自分を比較することに注力することが大切ということをアドバイスをさせて頂きました。 結構同じ悩みを抱えている人も結構いるんだなという印象です。 また他の登壇者の方々の発表を聞かせて頂きましたが、皆さん面白い内容が多く勉強になりました。 今回のイベントに参加してみて 参加してよかったというのが率直に感じたことです。 登壇という経験が出来たこともそうですが、懇親会では同年代のエンジニアの方々と開発している時の苦労であったり、考えているキャリアのことであったりと、色々と共有できて楽しかったです。 また是非機会があれば色々なイベントに参加していきたいなと考えています。
企画本部 AIソリューション部 今野です。 Safie Developers のPdMを担当しています。 過去に「 Safie APIの始め方と動作方法の紹介 」にて、Safie API β版の使い方を紹介させて頂きました。投稿から一年半以上経過する訳ですが、Safie APIはSafie Developersと同時にバージョンアップされ、現在はSafie API v2(正式版)として無事に公開することができています。過去の投稿の中ではβ版を正式版とすることが業務目標とお伝えしており、それを達成してこうしてまたBlogを投稿することができて嬉しい限りです。 本投稿では、Safie API v2(正式版)より提供を開始した無料トライアルを実際に使用してみた手順について紹介します。よろしくお願いいたします。 Safie Developers, Safie APIとは? トライアルに必要なものを揃える Safie APIをトライアルで動かしてみる ①Safie Developersでアプリケーションを作る ②APIキーとアプリケーションコードを取得する ③デバイス連携をする ④Safie APIでデバイス一覧を取得する ⑤Safie APIで画像を取得する 最後に Safie Developers, Safie APIとは? Safie Developersは、以前はSafie APIの紹介と問い合わせを受けるのみのサイトでした。現在は、ログイン機能が用意され、Safie APIの利用に必要な情報取得や各種設定ができるポータルサイトとなっています。 developers.safie.link Safie APIは変わらず、セーフィーが提供するクラウド録画サービスのデータを、外部のサーバーから取得したり、情報を書き足したりする機能を提供するものとなります。サーバーからの呼び出しを原則としているため、ブラウザから呼び出したい場合は Safie SDK(JavaScript) をご利用頂くこととなります。Safie SDK(JavaScript)については、改めて別の投稿で紹介したいと思っています。 Safie APIのv2(正式版)は、β版の認証情報は使用できない、メソッドが変更されている、等、様々な違いがあり、互換性は維持されていません。β版との互換性を維持しないことによる利用者のデメリットは理解していましたが、β版運用時に明らかとなっていた技術負債は軽視できるものではなく、正式版リリースを機に負債を解消して運用の安定化を行う決断をしました。正式版と銘打ってリリースした以上、今後は可能な限り仕様を公開し、後方互換を保って運用していく計画です。ご理解頂ければと思います。 互換性がなくなった分、β版ではできなかったことを大幅に盛り込みました。盛り込んだ推しの要素は以下となります。 クラウド録画サービスを契約しているだけでSafie APIのトライアルができる 認証に必要な情報がSafie Developersから待ち時間なしで取得できる Safie APIに関する各種設定がSafie Developersから行うことができる 認証方式を「OAuth2.0認証」に加え「APIキー」方式を利用できる β版では非公開だったRatelimitやエラー情報、など、機能制限の情報を確認できる β版では法人向けのみ公開だが、法人・個人の両方が利用できる 他にも様々な便利になった点があります。詳細は Safie Developers のサイトにてご確認ください。 トライアルに必要なものを揃える 早速ですが、トライアルに必要な環境を揃えていきます。 クラウド録画サービスを契約をしたカメラ(自分がオーナーのもの) Safie Developersへの登録 クラウド録画サービスを契約したカメラは、シェアされたものではなく、自分がオーナーとして契約したカメラであることが条件となっています。また、Safie Developersへの登録は以下の手順にて行います。 Safie Developers の右上の「ログイン」ボタンよりログインする ※アカウントはSafie Viewerと同じもの ディベロッパーとしての情報を入力し、利用規約を確認の上、登録する これにて準備は完了です。 Safie APIをトライアルで動かしてみる 私が具体的に動かした手順を紹介していきます。Safie APIはREST APIであり、多種多様な環境での呼び出しが可能なものです。今回の動作手順はあくまで一例にすぎませんが、動作理解の参考にして頂けると幸いです。環境の影響はほぼないかとは思いますが、動作環境を以下に記載しておきます。 MacBook Pro (13-inch, M1, 2020) macOS Ventura Version 13.4.1 (c) Google Chrome Version 116.0.5845.187 (Official Build) (arm64) Postman Version 10.17.3 https://www.postman.com/ ①Safie Developersでアプリケーションを作る まずはアプリケーションを作成しました。アプリケーションは自分が作成するサービスを表すものになります。アプリケーションを作成する際には、認証方式を選択することが必要となります。認証方式はOAuth2.0認証とAPIキー認証の2方式を提供しており、トライアルが実行できるのはAPIキー認証方式のみとなります。認証方式の違いに詳しく知りたい方は、Safie Developersのチュートリアルの 「 OAuth2.0認証 」「 APIキー認証 」をご確認ください。 Safie Developersにログインした後、「①-a 管理ツール」「①-b APIキー認証」「①-c アプリケーション新規作成」の順に選択しました(図1)。 図1. Safie Developers APIキー認証アプリケーション一覧(アプリケーション作成前) 「アプリケーションの新規作成」の画面にてアプリケーションの情報(表1)を入力し、「この内容で新規作成」を選択しました。 表1. アプリケーション新規作成 アプリケーション情報参考 項目名 パラメータ アプリケーション名称 テスト プラン トライアル 公開状況 非公開 利用サービス> 利用API 画像取得にチェック 「この内容で新規作成」を選択した後、「新規作成完了」のモーダルが出力されました(図2)。次にAPIキー作成の画面に進むため、「①-d APIキー管理に遷移する」を選択しました。 図2. Safie Developers アプリケーション新規作成完了モーダル ②APIキーとアプリケーションコードを取得する 前述手順を行うと、「APIキー認証アプリケーション>APIキー管理」の画面が表示された状態になります。ここからAPIキーとアプリケーションコードを取得し、記録しました。APIキーは、Safie APIを使うために必要な認証キーです。アプリケーションコードは、カメラにアプリケーションを認識させて、連携させるために使うコードとなります。 「APIキー認証アプリケーション>APIキー管理」の画面にて「②-1 APIキー新規発行」「②-2 発行」を選択し、APIキーを発行しました(図3, 図4)。「②-3 APIキー コピーアイコン」を選択し、APIキーを手元に記録しました(図5)。 図3. Safie Developers APIキー認証アプリケーション設定>APIキー管理画面(APIキー発行前) 図4. Safie Developers APIキー認証アプリケーション設定>APIキー管理画面 APIキー新規発行モーダル 図5. Safie Developers APIキー認証アプリケーション設定>APIキー管理画面(APIキー発行後) 「②-4 APIキー認証」を選択して「APIキー認証アプリケーション一覧」の画面に戻りました。「②-5 アプリケーションコード コピーアイコン」を選択して、アプリケーションコードを手元に記録しました(図6)。 図6. Safie Developers APIキー認証アプリケーション一覧(アプリケーション作成後) - 1 ③デバイス連携をする カメラの所有者側の立場で、②で記録したアプリケーションコードを使って、カメラにアプリケーションを認識させました。その後、サービスを作る側の立場でアプリケーションの利用を承認しました。 本来は、自分以外のカメラの所有者にアプリケーションコードを渡して、アプリケーションを認識してもらい、作成したサービスと連携してもらうのが正規の使い方です。今回は簡易なトライアルなので、アプリケーションを使うカメラの所有者側とサービスを作る側の両方を自分が兼ねています。 Safie Viewer を開き、「③-1 ユーザ設定」「③-2 Developers連携」の順に選択し、Developers連携の画面を開きました。「③-3 アプリケーションの追加」を選択し、「アプリケーションの追加申請」のモーダルを開きました(図7)。「③-4 アプリケーションコード」の入力枠に、記録していたアプリケーションコードを入力し、「③-5 次へ」を選択しました(図8)。「③-6 デバイス選択」にてアプリケーションを認識させたいカメラを選択しました(図9)。その後、申請内容確認画面が表示され、内容確認の上、「申請」を選択しました。 図7.Safie Viewer Developers連携 図8.Safie Viewer Developers連携 アプリケーションの追加申請モーダル 図9. Safie Viewer Developers連携 アプリケーションの追加申請モーダル カメラがアプリケーションを認識した上で、最後にサービスを作る側が承認を行わなければ、Safie APIは使用できない仕組みになっています。 Safie Developersを再度開き、「③-8 APIキー認証」を選択し、「APIキー認証アプリケーション一覧」の画面を開きました。「③-9 連携デバイス管理」を選択し、「APIキー認証アプリケーション>連携デバイス管理」の画面を開きました(図10)。 図10. Safie Developers APIキー認証アプリケーション一覧(アプリケーション作成後) - 2 「APIキー認証アプリケーション>連携デバイス管理」の画面では、アプリケーションコードを入力したデバイスの情報が表示されました。「③-10 設定」より「認証状況」を「承認済み」に変更しました(図11)。 図10. Safie Developers APIキー認証アプリケーション一覧(アプリケーション作成後) - 2 これにてSafie APIを使うための準備が全て整いました。 ④Safie APIでデバイス一覧を取得する アクセス可能なデバイス一覧を取得します。1台のみの登録なので、1台の情報のみ取得されます。デバイス一覧取得は特にパラメータ指定はないので、以下URLとAPIキーの設定のみを行います。 https://openapi.safie.link/v2/devices APIキーはAuthorizationのタブを選択し、Typeは「API Key」を選択しました。「Key」は「Safie-API-Key」の文字列を記入しました。「Value」は工程②で記録したAPIキーの文字列を記入しました。「Add to」は「Header」を選択しました。実行するとデバイス一覧がResponseに表示されました。表示された一覧からdevice_idの文字列を記録しました。 図11. Postman デバイス一覧取得実行 ⑤Safie APIで画像を取得する デバイスを指定して、画像取得を行いました。以下のURLの[device_id]の部分に、工程④で記録したdevice_idの文字列を記入しました。 https://openapi.safie.link/v2/devices/[device_id]/image 工程④の操作同様、AuthorizationにAPIキーを設定しました。実行するとResponseにカメラの画像が表示されました。 図12. Postman 画像取得実行 最後に 前回の投稿と同様の流れでしたが、Safie API v2(正式版)を実際に動かしてみた工程を紹介させて頂きました。Safie Developersのマニュアルに記載された内容ではあるのですが、今回の紹介を通して少しでも使い心地が伝わると嬉しく思います。 前回の紹介ではβ版は積極的に紹介できない旨を記載していましたが、正式版となり制限なく案内ができるようになりました。今回の投稿を見て気になった方は、是非、ご利用を検討頂ければと思います。