スライド共有サービス hellshake を作りました
※2018-02-26 プロジェクト名をリネームしました。 https://github.com/onk/hellshake/pull/36
はじめに
これは 【その1】ドリコム Advent Calendar 2015 - Adventar の 2 日目です。
1 日目は id:sue445 さんによる 社内gemとOSSのgemのメンテについて - くりにっき です。
今年のドリコム Advent Calendar は 2 本走るよ!
お前誰よ
-
id
-
ドリコム歴
- 2006/12/01 中途入社
- 10 年目に突入しました
-
仕事
- アプリケーションエンジニア
- Rails や Android アプリケーションを書いています
- 最近は 破綻なく物事を進める のが仕事になってきました
hellshake ってどんなもの?
- slideshare や speakerdeck みたいなものです
- ppt(x) や pdf をアップロードし、web 上で見ることができます
- スライドの内容から検索できます
- 自分でサーバを立てて社内用として利用することを想定しています
- デモ(閲覧専用)です。僕のスライド置き場でもある。 http://hellshake.onk.ninja/
使った技術
- いつものセット (ruby / rails / mysql / redis / memcached)
- libreoffice headless
- ppt(x) -> pdf への変換に使用
- PDF.js
- ブラウザ上での pdf 表示に使用
- poppler
- pdftotext で pdf から文字列の抽出
- pdftocairo で pdf を画像に変換
- elasticsearch
- 全文検索に
作るきっかけ
「社内勉強会のスライドが共有されなくなってきた」という危機感からです。
良い発表をしているのに、その資料がどこにも上がっていない。 ファイルサーバにディレクトリは掘ってあるんだけど誰も置かない。 「この間のあの発表、資料どこにある?」って聞いたらチャットで直接渡されたり。
- 上げる場所が決まっていない
- 検索性が悪い
のが原因じゃないかと思ったので作り始めました。
目的
- どこにファイルを置けばいいのかが明確になる
- チーム内の mtg のみに閉じていた資料が共有されるようになる
必要そうな要件
- web アプリケーションで pdf が見られる
- 全文検索できる
- スライド一覧がある
と決めた。要件の後ろ 2 つは「どこに上げるべきか」を考えなくて良いようにして、投稿のハードルを下げるためですね。
巨人の肩の上に立つ
ブラウザでスライドを見られる
speakerdeck のように、全ページ画像化して js でめくればいいかな?と一瞬思ったんですが、 「文字列を選択してコピー」とか「リンクのクリック」とかもできるようにしておきたかったので pdf.js を採用。
(pdf.js の存在は普段から Firefox ユーザなので知っていました)
pptx をそのままアップロードしたい
win32ole
かなぁ。でも linux サーバで動かしたいしなぁ、と思ってモヤモヤしていたところ、
libreoffice に --headless
オプションあるやん!ということで採用。
$ soffice --headless --convert-to pdf input.pptx
さすがに完璧な互換性を持っていなくてちょっと崩れるんですが、 まぁ slideshare でも崩れること多いしなーと妥協しました。
機能が無いよりはマシだし、気になる人は pdf で保存してから上げてくださいってことで。
表紙を画像で一覧表示したい
ghostscipt でゴニョるのかなぁ?って思ってたんだけど、ImageMagick がいい感じにラップしてくれてました。
$ convert input.pdf -resize 640 output.png
ちょっと画質悪いけどまぁ良いかと思っていたら、全文検索を実装中に pdftocairo でもっと綺麗に出力できることを知ったので乗り換え。
$ pdftocairo -png -singlefile input.pdf output
$ mogrify -resize 640 output.png
まさか希望通りに「表紙 (1 枚目) のみを画像にする」というオプションがあるとは思わなかったw
全文検索したい
xdoc2txt かなぁ。でも linux サーバで動かしたいしなぁ。と思いつつ検索していたら pdftotext を見つけたので、あとは solr か elasticsearch にでも突っ込めば終わり。
$ pdftotext -nopgbrk input.pdf
雛形が 1 週間でできた
「社内プレゼン共有ツールを作りたい」という思いは 2006 年末ぐらいからありました。 ドリコムが社内ブログ・社内 SNS を事業の一つにしていた頃ですね。slideshare が出てきたのもこの時期だったと記憶しています。
作ってみたら雛形は 1 週間程度で動いてしまい、「こんなに簡単に長年の夢が叶う時代なのか……」という気持ちです。
巨人の肩の上に立つのサイコー!! (FLOSS 的な文脈でこの言葉を使うとフリーライダー感が高まるんだけど、今回は本当に感動したので言っておきたかった
類似のもの
- azu さんの slide-pdf.js
- Ryuzee さんの open-slideshare
作成時の苦労
日本語用のフォントが使われず中国語っぽい表示になる
fc-match でどのフォントが使われるか判断できるようです。 このときに選択されるフォントで中国語字形が使われていると ppt を pdf に変換するときにツラい感じになる。
$ fc-match :lang=ja
DroidSansFallbackFull.ttf: "Droid Sans Fallback" "Regular"
$ fc-match :lang=ja
umeplus-p-gothic.ttf: "UmePlus P Gothic" "Regular"
日本語の字体だと安心感がありますね。
font を変えつつ色々試したんだけど、debian デフォルトのパッケージだと UmePlus フォント (fonts-umeplus) が読みやすくて良かったです。 ちゃんと ppt で使われているフォントに沿って適用するのが正しいとは思うんですが、まだ方法を見つけられておらず。
また、日本語フォントを入れて設定したつもりになってたんですが、capistrano 経由で sidekiq を立ち上げたときに
環境変数 LANG=C
となっており、その結果また中国語字形になってしまっていたので、環境変数 FC_LANG=ja
を設定するようにしました。
この記事が非常に参考になった。ロケールとフォント - みっどメモ
バカデカい表紙画像が生成される
15001x11250 というサイズの表紙画像が途中で生成され、リサイズ中にメモリ不足で落ちました……。 再現する pdf が手元にあるので、そのうち調べようと思います。たぶん pdf の dpi 指定か何かがおかしいんだと思う。
pdfjs-dist パッケージがそれ単体では使えない
前述の「文字列を選択してコピーとか、リンクのクリックとかもできるように」という処理に必要なファイルが含まれておらず、 npm や bower で完結できない。
結局 pdf.js の大部分をコピーして同梱してしまっています。
PDF.js で遊んでみた (ページの描画,テキスト・注釈の表示など) - きちぽよ〜 や、 pdf.js に含まれる web ディレクトリ を見ながら一つずつエラーを潰す感じでした。
読みやすい URL を作りたい
speakerdeck で漢字のファイル名が中国語読みの URL になってイライラするヤツの対策です。
mecab で形態素解析してフリガナを取り出し、カナをローマ字にするようにしました。
speakerdeck だと「開発進捗」が「kai-fa-jin-bu」になってしまいますが、 この方法なら「kaihatsu-shinchoku」と読みやすい URL を作ることができます。
全角数字の「1」の読み仮名が「イチ」になってしまったり、アンスコが邪魔だったりしたので 良い塩梅になるように調整しています。
str = "hoge_moge 空白 全角数字1入り混じり"
Zipang.to_slug(str)
#=> "hoge-moge-kuuhaku-zenkaku-suuji-1-iri-majiri"
こういうのを見るとカタカナから英語に変換する辞書も欲しくなりますねー。。ユーザ自身で slug を編集可能にすることで逃げました。
str = "ITエンジニア"
Zipang.to_slug(str)
#=> "it-enjinia"
参考:Ruby - 日本語をURL用ローマ字に変換するgem Zipangを作った - Qiita
kuromoji への依存はインストールが少し面倒なので natto gem を使うようにしています。
https://github.com/onk/hellshake/blob/master/lib/autoload/zipang.rb
社内展開時の苦労
そんなに苦労という苦労はしてないんですが、社内展開時に考えたことを。
アーリーアダプター気質を持った人は少々難があっても使ってくれるので、その先にリーチさせることを意識しています。
最低限のデザインを入れる
見るからに開発中の見た目だと使ってもらえないので、マシと思える程度のものにしてから展開しました。
ドメインを取る
IP アドレスで展開すると使ってもらえないので、社内の private DNS に登録しそれっぽいドメインにしました。
動作不良には最優先で対処する
社内ITシステムを構築・運用するのに最重要な3つのポイント - たごもりすメモ と同じかな。
エラーを勝手に検知して「今のエラー、xxx が原因でした。5 分ぐらい待ってねすぐ直す」とチャットで話しかける、という手段をとりました。 具体例だとアップロードするファイルタイプに validation がかかっておらず、エクセルのファイルを上げようとしていた人を見つけたので「ごめんね xlsx は対応してないんだわー」みたいな。
エラー通知を入れておくと、問い合わせに至らないケースも検知して対応することができます。 社内という閉じられた環境においても、エラーが起きた時に問い合わせてくれる人って 10 人に 1 人程度です。
コンテンツを確保する
こういった UGC サービスでは、コンテンツが集まってこない寂れたサービスだと思われたら鳴かず飛ばずで終わりです。 最初期においては、定期的に自分でコンテンツを集めてくる必要があります。
週次で行ってる部署ミーティングにて 5 分程度の発表を持ち回りでやっている部署が複数あるのを観測していたので、 各部署の長にアップロード先として使ってくれるようお願いして回りました。
「アップロードするだけで、ファイルサーバに置かなくても良い」というメリットがあるので、すんなり受け入れられたようです。
PV は運用開始してしばらくしてから見せる
最初のうちは僕の声が直接届く熱量の高いユーザが多いので、その熱量を PV という数字を追うのではなく 「情報共有」という理念を一緒に追って欲しいと思いました。
また、閲覧ユーザが少ないうちは、数字として少なさを実感してしまうと盛り下がってしまうので 最低限の DAU (7人程度) が担保できてから入れると良いのではないかと考えて、機能追加時期を見計らいました。
今後の機能追加になりますが、ユーザ自身が「アップしたら見てくれる人が居る」と思えるように、 見てくれそうな人を名指しで言える状況を作れるように、いわゆる「あしあと」機能を入れると良さそうです。
褒めつつステマする
みんながいるチャットで「xxx の資料良かったよー [URL]」という発言をすることで、
- 褒めることで気持ちよく
- 良い資料の共有
- サービス自体の認知度向上
を狙います。
だいたい、100 人いる部屋で URL を貼ると 30 人のアクセスがありました。
2 ファイル以上アップしてくれている優良ユーザの場合には、もっと気持ち良くなって欲しいので、 資料の直 URL ではなくユーザページの URL を貼ることで過去資料へも回遊させる、というコスい手も織り交ぜました。
ダンバー数を超えて広める
実は丸 4 ヶ月運用してまだ 170 名程度にしかリーチしていません。(300 人超のユーザがいるはずなので、約半数です)
ただ、この状態で毎朝の DAU は 10 を超えるようになりました。「新着があったら見たい」と思う人は一定数居てくれるようです。 (atom 配信もしているんだけど、社内用に RSS リーダを使っている人間は少ない)
理由はあくまで想像ですが、
- そもそも存在を知らない
- wiki に pdf を添付/表示できるので必要性が分からない
ではないかと考えています。
現状を打破するには
- 新着通知をチャットに流す
- iframe 等の手段で、外部の web ページ内に埋め込めるようにする
- wiki のプラグインを作り、埋め込みやすくする
- wiki やファイルサーバに上がっている ppt/pdf を見つけ、作成者に「hellshake にも上げてよー」と直接お願いする
等を行う必要があるんだろうなぁ。どれも「ただやるだけ」で難しくはないですね。
150 人までは「精神的な繋がりから来る己の強制力」で広めることができるんですが、その先にリーチするために努力し続けられるかが ちゃんとサービスとして成立するかどうかの境目なんじゃないでしょうか。
ソースコード
ソースコードは https://github.com/onk/hellshake に置いてあります。(MIT ライセンスです)
README や INSTALL にも書いていますが、
- ruby
- mysql
- redis
- memcached
- elasticsearch
- pdftotext
- pdftocairo
- libreoffice
が動いている必要があります。また、ppt->pdf 変換や表紙画像生成の非同期処理のために sidekiq も立ち上げておかなければなりません。
割と環境構築の難易度が高いと思うので、後ほど Dockerfile 置いておきますね。
社内ツール作成サークル
hellshake は以前 メタ勉強会で社内勉強会文化についてLTをしました #metabenkyokai - くりにっき でチラ見せしていたんですが、ここで発表された
- DATND (社内 ATND)
- hellshake (社内 slideshare)
の他にも
- Diita (社内 Qiita)
- だてブ (社内ソーシャルブックマーク)
- 調整ちゃん (社内調整さん)
- gemicom (社内 gemnasium)
- FavChatter (社内 Favstar)
- Gitpeach (社内 waffle.io)
等々、リバースエンジニアリングが趣味な人や、新しいものを作りたい人たちがサークル活動しています。
3 日目
次は @ogwmtnr さんの iOS - バックグラウンド時の位置情報常時取得にジオフェンスを駆使する手法を思いついたのでやってみた - Qiita です。