iTunesファイルをSSDに入れて別のPCで使えるようにする
本記事はiTunesのファイルをどうやって外部ストレージに保存し、 他のPCで聞けるようにするかについて説明します。
音楽好きの方々の中にはSpotifyなどAudio Streaming Platformに完全に移行できず、 ローカルにしか無い楽曲をiTunesで楽しんでる方もいるのではないかと思います。 そんな方々の音楽生活を豊かにするための参考になれば幸いです。
3行で
検証環境
- MacBook Pro Mid 2014 Sierra
- MacBook Pro 2018 Mojave
- itunes ver. 12.9.5.5
※Windowsは対象外です
iTunesのファイル構成
Macでは ~/Music/iTunes
に以下のようなファイル群が格納されている
ファイル or ディレクトリ名 | 説明 |
---|---|
iTunes Library Extras.itdb | Gracenote CDDB※1の情報が格納されているファイル |
iTunes Library Genius.itdb | iTunes Genius※2に関するファイル |
iTunes Library.itl | ライブラリ内の曲とユーザーが作成したプレイリストのデータベース |
iTunes Media | 実際の楽曲ファイル |
- ※1音楽CDの演奏者や制作年度などの情報が格納されたデータベース
- ※2ライブラリ内にすでにある音楽と関連のある新しい音楽をライブラリまたはiTunes Store内で見つける機能。
参考:
- https://www.macworld.com/article/1139974/itunes-files.html
- https://support.apple.com/ja-jp/guide/itunes/itns22073/mac
- https://www.lifewire.com/itl-file-2621843
コピー手順
- SSD直下に
iTunes
ディレクトリを作成し - 以下をSSDの
iTunes
ディレクトリにコピー~/Music/iTunes/iTunes Library Extras.itdb
~/Music/iTunes/iTunes Library Genius.itdb
~/Music/iTunes/iTunes Library.itl
~/Music/iTunes/iTunes Media
別PCとSSDにあるiTunesライブラリを連携
以下のシェルスクリプトはiTunesにすでにあるファイル群を削除します。 すでにiTunesで楽曲を管理しているPCに適用する場合は注意してください。
#!/bin/bash cd ~/Music/iTunes rm -f ./iTunes\ Library.itl ./iTunes\ Library\ Extras.itdb ./iTunes\ Library\ Genius.itdb rm -rf ./iTunes\ Media ln -s /Volumes/<あなたの外部ストレージの名前>/iTunes/iTunes\ Library.itl ./iTunes\ Library.itl ln -s /Volumes/<あなたの外部ストレージの名前>/iTunes/iTunes\ Library\ Extras.itdb ./iTunes\ Library\ Extras.itdb ln -s /Volumes/<あなたの外部ストレージの名前>/iTunes/iTunes\ Library\ Genius.itdb ./iTunes\ Library\ Genius.itdb ln -s /Volumes/<あなたの外部ストレージの名前>/maciTunes/iTunes\ Music/ ./iTunes\ Media cd -
上記のシェルスクリプトはすでにあるiTunesのファイル群を削除し、SSDにあるファイル群のシンボリックリンクを追加します。 このシェルスクリプトを実行後、iTunesを起動すると楽曲にアクセスできるようになります。
所感
以下のSSDをつかって使っています。
BUFFALO USB3.1(Gen1) 手のひらサイズ 小型ポータブルSSD 240GB ブラック SSD-PM240U3-B/N
- 出版社/メーカー: バッファロー
- 発売日: 2016/11/24
- メディア: Personal Computers
- この商品を含むブログ (1件) を見る
少し反応が遅いときもありますが基本快適に過ごせています。ネット環境が厳しくても気にせず好きな音楽聞けるのは嬉しいですね。
HerokuとPythonとSlackによるお手軽可視化システム
pandasやmatplotlib、他科学計算系のpackageを用いデータを定期的に可視化しチェックしたいケースがある。
この際特に大げさなシステムを作る必要がないし、金もねぇ、時間もねぇときがある。でもRedashじゃできねぇ...
そんな状況の中作ったHeroku、Python、Slackを用いたシステムについての備忘録。
目次
- Heroku Schedulerを設定
- pyplotでグラフを保存しSlackに通知
- 動的にmoduleをロードし、スクリプト追加を簡略化
1. Heroku Schedulerを設定
Heroku上で定期的にスクリプトを実行できるHeroku Schedulerというものがある。
適当にHerokuでappを作成した後、appにスクリプトファイルを配置する。
あとはSchedulerの設定画面でpython3 スクリプトファイル
を実行するよう設定すれば
pythonのスクリプトが定期的に実行される。便利。
この場合特にProcfileとか用意する必要はない。
Heroku CLIをインストールした後、以下のコマンドでappを作成
$ heroku create
以下URLに従いgitの設定をする
https://devcenter.heroku.com/articles/git
# heroku createした場合 $ git remove -v or # すでにherokuのappが存在する場合 $ heroku git:remote -a app名
なにかしらgitが整ったらHerokuのgitにpushし
$ git push heroku master
以下コマンドでHeroku Schedulerをappに追加
$ heroku addons:create scheduler:standard
tips
# schedulerの設定を開きたいときは $ heroku addons:open scheduler # ログを見たいとき $ heroku logs
Schedulerの設定では以下のようにpythonスクリプトを実行するように設定する。
2. pyplotでグラフを保存しSlackに通知
必要なもの:
Slack Web Apiを使うためにSlackのBotが必要になる。 python-slackclientはファイルアップロード機能を使うために利用する。
※当初SlackのIncoming Webhoookでbase64の画像をアップロードしようと思っていたが無理でした。
以下のようなスクリプトでSlackに簡単に画像が投稿できる
from matplotlib import pyplot matplotlib.use('Agg') import io import numpy import os import slack def main(argv): filename = "result.png" plot(filename) post(filename) os.remove(filename) def plot(filename): x = numpy.linspace(0, 10) y = numpy.sin(x) pyplot.plot(x, y) pyplot.savefig(filename, format="png") def post(filename): client = slack.WebClient(token=os.environ['SLACK_API_TOKEN']) response = client.files_upload( channels='#random', file=filename, title="test", filename=filename) if __name__ == '__main__': main(sys.argv)
画像の生成はtempfile.NamedTemporaryFile
を使う方が好ましく当初それで作成していた。
なぜかうまくSlackの投稿でサムネイルが表示されなくなったため、result.pngを保存するようにした。
SLACK_API_TOKEN
は環境変数を参考するようにしており(参考)、
開発時にはpython-dotenvを使うと良いと思われる。
Herokuには以下のコマンドで環境変数を設定する
$ heroku config:set SLACK_API_TOKEN=トークン
あとはHerokuになんのpackageを使っているか伝えるためrequirements.txtを配置する。
$ pip freeze > requirements.txt
これで下記画像のようなものがSlackに投稿される。
3. 動的にmoduleをロードし、スクリプト追加を簡略化
今後も追跡したいデータとそれにまつわる可視化のグラフは増えそう。 簡単にグラフを追加できるようにする。
以下のようなディレクトリ構成
- app.py - jobs |- some_job | |- __init__.py | |- analyzer.py | |- another_job |- __init__.py |- analyzer.py
app.py
は2.のものを改変し以下のような形にする
from datetime import datetime from dotenv import load_dotenv load_dotenv() import importlib import os imporo sys import slack def main(argv): jobs_dir = os.listdir('jobs') for job_dir in jobs_dir: m = importlib.import_module("jobs.%s.analyzer" % job_dir) filename = "result.png" try: if os.path.isfile(filename): os.remove(filename) m.plot(filename) post(job_dir, filename) finally: if os.path.isfile(filename): os.remove(filename) def post(job_dir, filename): client = slack.WebClient(token=os.environ['SLACK_API_TOKEN']) response = client.files_upload( channels='#random', file=filename, title="%s_%s.png" % (job_dir, datetime.now().strftime("%Y_%m_%d")), filename=filename) if __name__ == '__main__': main(sys.argv)
ディレクトリ名、メソッド名はもうちょい良い感じにしていただければ。
importlib
を用いてjobsディレクトリ配下のmoduleをimportする。そのためには空でもいいので__init__.py
が必要らしいので作成しておく(間違ってる可能性あるのでツッコミください)。
各moduleにはanalyzer.py
というファイルがあり、plot
メソッドでresult.png
という画像を保存する。
以下例:
analyzer.py
import matplotlib from matplotlib import pyplot matplotlib.use('Agg') import numpy import io def plot(filename): image = io.BytesIO() x = numpy.linspace(0, 10) y = numpy.sin(x) pyplot.plot(x, y) pyplot.savefig(filename, format="png")
このような各moduleのanalyzer.py
をapp.py
から動的に読み込み、plot
メソッドを随時呼び出して画像を作成、そしてSlackに投稿という流れになる。
新しく定期的にplotしたいものが増えた場合、jobsディレクトリにディレクトリを新規作成しanalyzer.py
を用意しplot
メソッドを定義すればよい。
まとめ
HerokuとPythonとSlackによる可視化システムについて説明しました。時間がほぼないなかさっとつくったにしては結構便利です。 前々からRedashだけだと足りないが、壮大なシステムを作るほどでもないケースが多かったのでこれからも重宝しそう。 個人的な理想としてはRedashと定期的にJupyter Notebookが動作するようなシステムがあればそれで十分なんだけどなーと思うのですがあるのでしょうか。 あったら教えてください偉い人!
余談ですが、これまでpipenvをつかっていたが、venvが便利なことに気づく。
Pythonは四半期に1回ちょっと使う程度なので間違いがあればご指摘お願いします。
twirp-ruby概要
はじめに
twirpというgRPCと似たようなRPCフレームワークを触っている中でのメモ。twirpはgRPCと似ていますがHTTP2に限定されずHTTP1.1でも使用できる便利なやつです。
基本
登場人物
Service
...ProtocolBufferで定義されたService。その中身は実はRackアプリケーション- 合わせて読もうRackとは何か - Qiita
Handler
...Serviceがどう動くかを定義Client
...Service呼ぶやつ
ServiceはServiceをRackアプリケーショとして定義するが、どう動くかについては定義していない。Handlerを差しこむことで中身の動きを定義する 例:
HogeService.new(FugaHandler)
ちなみに以下のような形でHookポイントがあるので、各Hookポイントで処理を書くことが可能
routing -> before -> handler -> on_success -> on_error
具体的なService, Handler, Clientのコードは以下となる
module Example class HelloWorldService < Twirp::Service package "example" service "HelloWorld" rpc :Hello, HelloRequest, HelloResponse, :ruby_method => :hello end class HelloWorldClient < Twirp::Client client_for HelloWorldService end end class HelloWorldHandler def hello(req, env) if req.name.empty? return Twirp::Error.invalid_argument("name is mandatory") end {message: "Hello #{req.name}"} end end
Service内で使用しているメソッド詳細
package
... Serviceのパッケージ名を定義。まじでパッケージ名的なことにしか使われないservice
...Serviceのサービス名を定義。まじでサービス名的なことにしか使われないrpc
...Twirp::Service
にはrpcsというrpcの定義をためる変数がある。そこにrpcを追加する
rpcsには以下のようなデータが追加される
twirp-ruby/service_dsl.rb at 3ec36d2653a14eb8cc73409fb20889e8484db371 · twitchtv/twirp-ruby · GitHub
rpcdef = { rpc_method: rpc_method.to_sym, # as defined in the Proto file. input_class: input_class, # google/protobuf Message class to serialize the input (proto request). output_class: output_class, # google/protobuf Message class to serialize the output (proto response). ruby_method: opts[:ruby_method].to_sym, # method on the handler or client to handle this rpc requests. } @rpcs ||= {} @rpcs[rpc_method.to_s] = rpcdef
Clientからの呼び出し方法
# Equivalent RPC calls client.rpc(:Hello, HelloRequest.new(name: "World")) # generic rpc method client.hello(HelloRequest.new(name: "World")) # DSL method with message object client.hello(name: "World") # DSL method with message attributes
gRPCと違い、Requestクラスを使わずともHashで呼べる
Client呼び出し時の戻り値
The response is a Twirp::ClientResponse object with the properties data (success) and error (failure).
しかも、errorは Twirp::Error
が返される。gRPCと違い直接ProtocolBufferで定義したmessageを返さないので注意。
Rails連携
Twirp::Rails.services
にservice一覧を保持bindメソッド
をHandler中に記載することでHandlerをServiceに紐づけて上記service一覧に追加config/routes.rb
内にuse_twirp
と書くことによりserviceのrpcメソッドに対応したルーティングを生成する- twirp-rails/routes.rb at e07923de2b1cdc371b157d82765735a3ba2d3fe0 · nikushi/twirp-rails · GitHub
- Railsはrackアプリケーションにルーティングすることができるので、この機能を用いる(Rails のルーティング - Rails ガイド)
RequestId付きのRailsのログをvimで便利に見る
Railsではconfig.log_tags
にuuid
を指定することでRequestId付きのログを出力できます。
RequestIdつきのログを確認するとき、以下のような欲望があります。
- 特定のパターンでフィルタしたい
- マッチした行だけでなく、関連するRequestIdの行を全部表示し、リクエスト全体の流れが知りたい。
例えば特定のControllrのActionのログをフィルタしたいときや、特定のユーザーのログを見たいときなどです。 vimで関数を定義することで実現できたので記しておきます。
検証環境:
- NeoVim v0.3.1
- ag.vim
Railsのログはconfig/application.rb
とかに以下のようなconfigがはいってるやつです。
config.log_tags = [:uuid]
続きを読む
Parser gemを用いたプロファイルコードの挿入
Rubyで簡易なプロファイル用のコードを挿入し、プロファイリングするにはどうしたらいいのか興味が出たのでやってみました。最終的にはwhitequark/parser を用いたRewrite処理で実現できました。
JavaScriptの関数の開始と終了にプロファイル用のコードを挿入し、シンプルなプロファイリングをするという記事が以下:
ASTの一つの使い方としてとても面白いです。
続きを読むデータ起点でのプロダクト改善の取り組み: 8月
こんにちは。普段はClearと呼ばれる教育系アプリに対して、Ruby on Railsでの開発やインフラの整備、Androidのレビューを行っています。趣味でアクセスログ解析を行っていました。
2018年8月からプロダクトの開発方針を変更し、データの観点からもアプリの各種KPI向上を目指すことになりました。 そこでの取り組みについて、まだまだ手探りですが誰かの役に立つかもしれないので備忘録を兼ねて記しておきます。
前提
- 世界で200万DLくらいのC to C学習アプリ
- アプリからのアクセスログはAWS Redshiftにたまっている
- データ観点での施策は既存機能にまつわる課題の解決に留める。より大きな目線での課題解決はデザイナーが担当
なぜやるのか
これまでの開発方針ではMAUなどの主要KPIの増加を狙うため施策を行っていましたが、個人的に以下の問題があると感じていました
- 施策に効果があったか評価をしない
- 施策に効果があるかどうかわからないまま結構な工数を消費しがち
またこれまでユーザーへのインタビューなど行い、ペルソナなどもつくっていましたが、うまくそれをプロダクト開発に活用できていないのも気になっていました。仮説に対する学びを得る、無駄な工数を減らす、ユーザーから得られた情報を活かすという想いから開発方針の変更に至りました。
こんな人におすすめ(だと思う)
- リーンスタートアップやInspiredをよんだが何したらいいのかいまいちわからない人
- 僕もよくわからないので試行錯誤してる最中です
- プロダクトチーム5人以下の小さな会社
- おそらく大きな会社だとグロースチームや分析チームなどいろいろな役職の人がいるので、より効率的なやり方があると思います。