はじめに
スマホ、触りすぎていませんか?
私は隙があればついついスマホでYouTubeやSNSを長々と見てしまいます。YouTubeを始めた芸能人も多く、無限にコンテンツを楽しめてしまいますよね。コロナ渦で自宅にいることが増えたこともあってか、スクリーンタイムを見て唖然としてしまう日も少なくありません...。
そんな中、スクリーンタイムをSNSに投稿して勉強のモチベーションにしている受験生を見て、こういう使い方もあるんだなぁと感心しました。
とはいえ、わざわざ設定画面を開いてスクショを撮り、それをトリミングしてSNSに手動で投稿するのは少々面倒に感じます()
幸いなことに、macからも同じApple IDで登録されてデバイスのスクリーンタイムを見ることができます。また、macにはAutomatorという操作を自動化するアプリケーションがあります。
さらに、Googleが公開しているCloud Vison APIを使えば、画像から文字を抽出することができます。
これらを上手いこと使って自動で「iPhoneのスクリーンタイムをデータとして記録する」までを行ってみました。
日々の生活を記録することで自己管理を効率化できるのではないかと思います!
スクリーンタイムについて
スクリーンタイムで見れる項目には、
- App使用時間
- 通知
- 持ち上げ/再開回数
があります。
macのスクリーンタイム画面からは、サイドバーからこれらを選択して各項目の利用状況のグラフを見ることができます。注目すべきはシステム環境はウインドウサイズが一定で、スクリーンタイム内の文字やグラフの配置も同じような箇所にあることです。そのため、OCRで読み取りたい箇所だけを決め打ちでトリミングできます。
Automator
文字認識をしたいスクリーンタイムの画像を取得するためにAutomatorを使います。
Automatorの大まかな流れはこのような感じです。
- システム環境設定を開く
- 操作を記録して、スクリーンタイムを開き、取得したいデバイスを選択する
- 「App使用時間」「通知」「持ち上げ/再開回数」それぞれでスクリーンショットを撮影 & OCRしたい箇所をトリミング
- トリミングした画像をくっつけてVisonAPIでテキスト取得、スプレッドシートに記録
Automatorの詳細
AppleScript
「アプリケーションを開く」でシステム環境設定を開くと画面が手前にならないことがあり、操作を記録のステップで処理がコケてしまうのでAppleScriptで起動しています。
tell application "System Preferences"
activate
end tell
操作を記録
Automatorアプリの(記録)ボタンを押して、システム環境設定 > スクリーンタイム > デバイスの選択 > 日付を昨日に変更 までの流れをを記録させています
シェルスクリプトを実行
screencapture
コマンドで画面のスクリーンショットを撮影します。-l
オプションで指定したwindow1dの画面を撮影することができます。また、-x
は撮影音OFF、-o
はスクリーンショットの影をなくすオプションです。
前の手順でクリックした直後に撮影しないように念のためシェルスクリプトの最初でsleep 1s
としています。
sleep 1s
dir="$HOME/lifelog"
filepath=$dir/`date -v -1d +%Y%m%d`_screentime.png
crop="/tmp/cropped_1.png"
screencapture -xo -l$(osascript -e 'tell app "システム環境設定" to id of window 1') $filepath
/usr/local/bin/convert $filepath -crop 828x574+466+152 $filepath # パスが通っていないので、フルパスで書く
/usr/local/bin/convert $filepath +repage -crop 400x60+20+60 $crop
操作を記録
システム環境設定のサイドバーにある「通知」のクリック操作を記録しています。「通知」をクリックした後は上記と同じ内容のシェルスクリプトを実行します。「持ち上げ/再開」でも同様に行います。
画像の結合とVisionAPI
/usr/local/bin/convert /tmp/cropped_1.png /tmp/cropped_2.png /tmp/cropped_3.png -append /tmp/combined.png
python record_screentime.py # Vision APIとシートに記録
スクリーンショットとトリミング
macでは、screencapture
コマンドでCLIからスクリーンショットを撮影できます。
トリミングにはImageMagickのconvert
コマンドを使用しています。-crop
オプションの値には、(width)x(height)+(left)+(top)
を指定しています。
また、一度cropした画像にさらにcropしようとするとconvert: geometry does not contain image
というエラーが出てしまいましたが、-crop
の前に+repage
をつけることで解消できました。
# ウインドウを指定してスクリーンショットを撮影
screencapture -xo -l$(osascript -e 'tell app "システム環境設定" to id of window 1') screentime.png
# crop
convert screentime.png -crop 828x574+466+152 screentime.png
# OCRしたい箇所でさらにcrop
convert screentime.png +repage -crop 400x60+20+60 screentime_cropped.png
上記コマンドでOCRで文字認識したい箇所でcropすると、
- App使用時間
のようになります。これらを結合した画像をVisino APIに投げます。画像の結合は、以下のコマンドで行いました。+append
で縦方向、-append
で横方向に結合できます。
convert /tmp/cropped_1.png /tmp/cropped_2.png /tmp/cropped_3.png -append /tmp/combined.png
結合した画像
これで準備完了です。
Vision APIとシートに記録
いよいよ準備した画像を使って、文字認識を行ってデータとして保存します。
以下の記事などを参考にさせていただきました。
- PythonでGoogleのCloud Vision APIを利用して画像から日本語文字検出する
- 【Google Colab】Vision APIで『レシートOCR』!
- Pythonでのスプレッドシート操作方法(gspreadの使い方)
import gspread
import json
from datetime import datetime, timedelta
from oauth2client.service_account import ServiceAccountCredentials
import os
import io
import re
from google.cloud import vision
credential_path = '【サービスアカウントキーのパス】'
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = credential_path
file_path = "/tmp/combined.png"
with io.open(file_path, "rb") as image_file:
content = image_file.read()
image = vision.Image(content=content)
client = vision.ImageAnnotatorClient()
response = client.text_detection(image=image)
data = response.text_annotations[0].description.split() # [0]でfull textを取得
scope = ['https://spreadsheets.google.com/feeds','https://www.googleapis.com/auth/drive']
credentials = ServiceAccountCredentials.from_json_keyfile_name(credential_path, scope)
gc = gspread.authorize(credentials)
SPREADSHEET_KEY = '【スプレッドシートのキー】'
worksheet = gc.open_by_key(SPREADSHEET_KEY).sheet1
yesterday = datetime.today() - timedelta(days=1)
date = datetime.strftime(yesterday, '%Y/%m/%d')
d = re.findall("\d+", data[0]) # 'xx時間yy分` -> ['xx','yy']
d = list(map(int, d))
if len(d) == 2: # xx時間yy分の場合
data[0] = d[0]* 60 + d[1]
elif len(d) == 1: # yy分の場合
data[0] = d[0]
data = list(map(int, data))
data.insert(0, date)
worksheet.append_row(data, value_input_option="USER_ENTERED")
スクリーンタイムのデータがシートに反映されました!
あとはAutomatorのアプリを起動すれば今までの処理を自動で行ってくれます。(本当はcronで設定したかったけど、画面操作があるためできませんでした。。)
ちなみに、VisionAPIを使った文字認識の結果はこうなりました。緑がParagraph、黄色が文字を表しています。きれいに認識できていますね。
おわりに
自動化ソフトや画像認識のツールを使って、スクリーンタイムをログに残してみました。せっかくならスクショだけはでなくて数字で記録に残せるといいですよね。
VisionAPIは1ヶ月1000リクエストまで無料なので毎日スクリーンタイムを記録して問題なさそうです。
今のところスクリーンタイムを記録する術は英語でググっても見つからなかったので、この記事が誰かの参考になれば幸いです。
(Appleさん、スクリーンタイムもヘルスケアから読み取れるようにしてください)