rcloneでAmazonCloudDriveにデータを暗号化して同期する


2017/6/4
RcloneのAmazonCloudDrive接続がClientIDが無効になったことによりできなくなっています。
https://forum.rclone.org/t/rclone-has-been-banned-from-amazon-drive/2314

rcloneが暗号化に対応したと聞いて試してみた。

やること

rcloneを使用してローカルのファイルをAmazonCloudDriveと同期する。
rcloneの機能でAmazonCloudDrive上にデータをアップロードする際は暗号化し、ダウンロードする際は復号化する。

暗号化の必要性

Amazon Cloud Drive利用規約を読むと、アマゾンがファイルにアクセスすることもありうる内容になっている。
私がアヘ顔ダブルピースしているホームビデオを見られる可能性があると困るため、暗号化してファイルを置くことが必須となる。

確認環境

ローカル側
– Ubuntu 16.04
– rclone v1.35
– Windows10(認証用)

リモート側
– Amazon Cloud Drive(プライム会員の5GB)

手順

手順は以下を参考にした。
https://www.reddit.com/r/DataHoarder/comments/598pb2/tutorial_how_to_make_an_encrypted_acd_backup_on/

Ubuntuへのrcloneインストール

ほぼ公式に書いてある手順と同一。

mkdir -p ~/work/rclone
cd ~/work/rclone

sudo apt install unzip

curl -O http://downloads.rclone.org/rclone-current-linux-amd64.zip
unzip rclone-current-linux-amd64.zip
cd rclone-*-linux-amd64

sudo cp rclone /usr/sbin/
sudo chown root:root /usr/sbin/rclone
sudo chmod 755 /usr/sbin/rclone

sudo mkdir -p /usr/local/share/man/man1
sudo cp rclone.1 /usr/local/share/man/man1/
sudo mandb

rcloneにAmazonCloudDriveを設定

実行ユーザ毎に設定が作られる。
途中で入力するトークンは後述の方法で入手した。

$ rclone config
2017/--/-- --:--:-- Config file "/home/test/.rclone.conf" not found - using defaults
No remotes found - make a new one
n) New remote
s) Set configuration password
q) Quit config
n/s/q> n <-新規に設定を作成
name> ACD <-設定の名前をつける
Type of storage to configure.
Choose a number from below, or type in your own value
 1 / Amazon Drive
   \ "amazon cloud drive"
 2 / Amazon S3 (also Dreamhost, Ceph, Minio)
   \ "s3"
 3 / Backblaze B2
   \ "b2"
 4 / Dropbox
   \ "dropbox"
 5 / Encrypt/Decrypt a remote
   \ "crypt"
 6 / Google Cloud Storage (this is not Google Drive)
   \ "google cloud storage"
 7 / Google Drive
   \ "drive"
 8 / Hubic
   \ "hubic"
 9 / Local Disk
   \ "local"
10 / Microsoft OneDrive
   \ "onedrive"
11 / Openstack Swift (Rackspace Cloud Files, Memset Memstore, OVH)
   \ "swift"
12 / Yandex Disk
   \ "yandex"
Storage> 1 <-AmazonCloudDriveを使うので1
Amazon Application Client Id - leave blank normally.
client_id> <-空Enter
Amazon Application Client Secret - leave blank normally.
client_secret> <-空Enter
Remote config
Use auto config?
 * Say Y if not sure
 * Say N if you are working on a remote or headless machine
y) Yes
n) No
y/n> n <-確認したのがブラウザが開けない環境だったので、nで進めた
For this to work, you will need rclone available on a machine that has a web browser available.
Execute the following on your machine:
        rclone authorize "amazon cloud drive"
Then paste the result below:
result> *** <-後述の方法で入手したトークンを貼り付け
--------------------
[ACD]
client_id =
client_secret =
token = ****
--------------------
y) Yes this is OK
e) Edit this remote
d) Delete this remote
y/e/d> y <-設定完了
Current remotes:

Name                 Type
====                 ====
ACD                  amazon cloud drive

e) Edit existing remote
n) New remote
d) Delete remote
s) Set configuration password
q) Quit config
e/n/d/s/q> q <-一旦終了

認証を別端末のWindows10で行う

rcloneのWindows版をダウンロードしてきて、コマンドプロンプトで以下を実施。
途中でブラウザからアマゾンの認証画面が開かれるので、ログインする。

C:\test>rclone authorize "amazon cloud drive"
2017/--/-- --:--:-- Config file "C:\\Users\\test/.rclone.conf" not found - using defaults
If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth
Log in and authorize rclone for access
Waiting for code...
Got code
Paste the following into your remote machine --->
**** <-ここに表示されるのがトークン
<---End paste

rcloneに暗号化するディレクトリを設定

AmazonCloudDrive上で暗号化するため必要な設定をする。

$ rclone config
Current remotes:

Name                 Type
====                 ====
ACD                  amazon cloud drive

e) Edit existing remote
n) New remote
d) Delete remote
s) Set configuration password
q) Quit config
e/n/d/s/q> n <-設定を作成
name> ACD_crypt <-設定に名前をつける
Type of storage to configure.
Choose a number from below, or type in your own value
 1 / Amazon Drive
   \ "amazon cloud drive"
 2 / Amazon S3 (also Dreamhost, Ceph, Minio)
   \ "s3"
 3 / Backblaze B2
   \ "b2"
 4 / Dropbox
   \ "dropbox"
 5 / Encrypt/Decrypt a remote
   \ "crypt"
 6 / Google Cloud Storage (this is not Google Drive)
   \ "google cloud storage"
 7 / Google Drive
   \ "drive"
 8 / Hubic
   \ "hubic"
 9 / Local Disk
   \ "local"
10 / Microsoft OneDrive
   \ "onedrive"
11 / Openstack Swift (Rackspace Cloud Files, Memset Memstore, OVH)
   \ "swift"
12 / Yandex Disk
   \ "yandex"
Storage> 5 <-暗号化設定なので5
Remote to encrypt/decrypt.
Normally should contain a ':' and a path, eg "myremote:path/to/dir",
"myremote:bucket" or maybe "myremote:" (not recommended).
remote> ACD:/DataBackup/ <- 設定ディレクトリ(書き方は後述)
How to encrypt the filenames.
Choose a number from below, or type in your own value
 1 / Don't encrypt the file names.  Adds a ".bin" extension only.
   \ "off"
 2 / Encrypt the filenames see the docs for the details.
   \ "standard"
filename_encryption> 2 <-ファイル名の暗号化をする場合は2
Password or pass phrase for encryption.
y) Yes type in my own password
g) Generate random password
y/g> g <-暗号化パスワードを自動生成
Password strength in bits.
64 is just about memorable
128 is secure
1024 is the maximum
Bits> 128
Your password is: dw37uhP1Dl56Fhr8DYuZjg
Use this password?
y) Yes
n) No
y/n> y <-暗号化パスワードを承認
Password or pass phrase for salt. Optional but recommended.
Should be different to the previous password.
y) Yes type in my own password
g) Generate random password
n) No leave this optional password blank
y/g/n> g <-暗号化のソルトを自動生成
Password strength in bits.
64 is just about memorable
128 is secure
1024 is the maximum
Bits> 128
Your password is: 8UubLhAxmfQc1Cvs3UbuQw
Use this password?
y) Yes
n) No
y/n> y <-暗号化のソルトを承認
Remote config
--------------------
[ACD_crypt]
remote = ACD:/DataBackup/
filename_encryption = standard
password = *** ENCRYPTED ***
password2 = *** ENCRYPTED ***
--------------------
y) Yes this is OK
e) Edit this remote
d) Delete this remote
y/e/d> y <-設定に問題なければy
Current remotes:

Name                 Type
====                 ====
ACD                  amazon cloud drive
ACD_crypt            crypt

e) Edit existing remote
n) New remote
d) Delete remote
s) Set configuration password
q) Quit config
e/n/d/s/q> q <-設定ウィザードを終了

設定ディレクトリの書き方

(クラウドストレージの設定名):(ディレクトリ)
なので、上述の設定ではAmazonCloudDrive上のDataBackupディレクトリ内に暗号化したファイルを置く設定となる。

ルートに暗号化したデータを置く場合は以下の例のようにディレクトリを空にするらしい?(未検証)
– ACD:

ファイルを暗号化/復号化して同期

ローカルからAmazonCloudDriveに暗号化して同期

ローカルの/dataディレクトリからAmazonCloudDriveの/DataBackupディレクトリに同期する場合。

rclone sync /data ACD_crypt:/DataBackup/

こんな感じに暗号化されたファイル/ディレクトリができる。

AmazonCloudDriveからローカルに復号化して同期

AmazonCloudDriveの/DataBackupディレクトリからローカルの/dataディレクトリに同期する場合。

rclone sync ACD_crypt:/DataBackup/ /data

その他

  • Linuxのrcloneでアップロードしたファイルを、Windowsのrcloneで暗号化パスワードとソルトを同一にしてダウンロードすることもできた。
  • 以前にEncFSを使用して暗号化する方法も検討していたのですが、暗号化したファイルを一時的にでもローカルに置く必要がある点がネックになってました。rcloneだけでできればシンプルで便利。
  • ACDだとファイルとフォルダの名前は半角で255文字以内である必要があるのですが、ファイル名/フォルダ名の暗号化により文字数が増えて制限を超える可能性もあります。制限を超えると、rclone実行時に「failed to satisfy constraint: Member must have length less than or equal to 280」というエラーが出るかもしれません。

Space EngineersのDedicatedサーバをWindowsで構築する

内容について

ほとんど以下の公式ページに書いてあります。
http://www.spaceengineersgame.com/dedicated-servers.html

SpaceEngineersのサーバを立てる際に自分がやった内容を残しておきます。
とはいえこのゲームをやるEngineerならこの程度は問題とならないような気もしますが、手間を省く一助となれば幸いです。
ちなみに、Dedicatedサーバはゲームクライアントを起動せず、スタンドアローンのサーバアプリケーションのみを起動して使うものになります。

確認環境

この内容は全て以下の環境で確認しています。
特にSpaceEngineersはBeta版での確認となるため、仕様が変更となる可能性が大きくあります。

  • SpaceEngineers 01.168 Stable
  • Windows10 64bit

Dedicatedサーバのインストール

SteamクライアントでダウンロードするゲームアプリケーションにもDedicatedサーバが同梱されていますが、ここではSteamCMDでダウンロードする方法をとります。

SteamCMDの準備

以下からSteamCMDをダウンロードして、適当な場所に解凍。
https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip

ダウンロード/アップデートバッチの作成と実行

「steamcmd.exe」と同じディレクトリに以下の内容のバッチファイルを作成。
名前は任意なので、ここでは例として「SE_inst_updt.bat」とする。

※「C:\SE」の部分はDedicatedサーバのインストール先となるため。任意に変更する。
※app_updateで指定するIDはここを参照。

@echo off
start "" steamcmd.exe +login anonymous +force_install_dir "C:\SE" +app_update 298740 validate +quit

作成後、バッチを実行し、終わるまで待つ。

以上で、インストールは完了。

サーバの起動

サービスへの登録を行う場合、以下の作業はAdministrators権限のあるユーザで行うこと。

サーバ管理アプリケーションの起動

[(バッチで指定したインストールフォルダ)\DedicatedServer64\SpaceEngineersDedicated.exe]を起動。

インスタンス選択画面

インスタンス(サービス/OS起動時の自動起動)を設定するか否かで以下の手順が異なります。

インスタンスを作成しない場合

「Lcal/Console」を選択して「Continue to Server Configuration」を押す。

インスタンスを作成する場合

「Run as Admin」ボタンで管理者権限を与えて、「Add new instance」ボタンからインスタンス名を決めて作成。
その後、作成したインスタンスを選択して「Continue to Server Configuration」を押す。

サーバ設定画面

ここの設定値については、ドキュメントが見つからなくってよくわからない部分が多い。

とりあえず、新規にワールドを作るときは以下になる。
1. Nwe gameを選択
2. Scenarioを選択
3. Server portが標準のUDP27016意外であれば変更(当然ですが、NAT等でインターネットからアクセス可能であること)
4. Server nameを入力(サーバリスト上で表示される)
5. World nameを入力(サーバリスト上で表示される)
6. 適当にその他の設定値を入力。
7. Save & startでサーバを起動

これで、ゲーム上のサーバリストから見えて、サーバに入ることができる状態になっている。

以前に作成したワールドを再度起動する場合

Saved worldsと、起動したいワールド名を選択して起動。

インスタンスで自動起動されるワールド

最後に起動したワールドが自動起動で使用されているように見えるが、設定場所も正確な記述もわからなかった。

アップデート

SpaceEngineersは定期的にアップデートがあり、ほとんどの場合、新しいクライアントから古いサーバへはアクセスできなくなる。
そのため、ある程度定期的にサーバのアップデートが必要になると思われる。
サービスを停止してバッチを動かすだけのため、自動化もむすかしくはなさそう。

アップデート方法

サーバをサーバ設定の「Stop」ボタンで停止し、インストール時に使用したバッチファイルを実行する。

Modの設定

ワールド内で、ワークショップで公開されているModが使用できる。

ModのIDを調べる

ワークショップのページから適当に入れたいModを探しページを開く。
URLの後ろの方の[id=]の後の数字をメモする。

サーバ設定

サーバ設定のModタブに入力する。
複数の場合は改行して入力していく。

あとは起動すればModの内容が使用可能な状態となっており、クライアントが接続するとクライアント側で必要なModのデータがダウンロードされるようになる。
一度ダウンロードすれば2度目以降は差分のみとなるため、素早くサーバに入れる。

適用されないMod?

ブループリントとスクリプトはサーバで指定しても出てこないっぽい?
クライアントでサブスクライブしてれば使えるから?

グループメンバーのみが入れるように設定する

サーバは公式のリストに載せられてしまうため、そのままだと誰でも簡単に入ってこれる状態となる。
しかし、Steamで作成したグループのメンバーのみがサーバに入れるよう設定することができる。

グループを作成

Steamクライアントからであれば、以下で作成画面に行ける。

  1. (ユーザ名)->グループを選択。
  2. 「新しいグループを作成」をクリック。

グループを作ったら、サーバに入れるようにしたいユーザを招待する。

グループIDを調べる

グループ管理画面から「フレンドを招待」をクリックし、その後のページのURLの「invitegid=」の後の数字列がグループID。
(例)http://steamcommunity.com/profiles/???????????/friends/?invitegid=(グループID)

サーバ設定

サーバ設定の「Steam Group IDに調べたグループIDを入力して起動。

waifu2x-caffeとffmpegで動画を拡大するPowerShellスクリプト

どういうものか

waifu2xという、機械学習の結果を利用して、画像をきれいに拡大したり、圧縮時のノイズを除去したりするソフトウェアが公開されています。
そのWindows向けビルドがwaifu2x-caffeで、動画変換ソフトのFFmpegと組み合わせることで動画をきれいに拡大することができるため、PowerShellスクリプトで自動的に処理を流せるようにしました。

※waifu2xの処理は動画向けではないため、元々大きいサイズの動画があれば、もちろんそちらのほうが良いです。

各コマンドは「RICOH THETA Sの動画機能を4k相当に拡張する(waifu 2x で) – izm_11’s blog」を参考にさせていただきました。

対象フォルダに入れた動画を以下の流れで変換します。

  1. ffprobe(FFmpegに付属)で対象の動画情報を取得
  2. ffmpegで音声を分離
  3. ffmpegで動画を1コマずつ画像に分離
  4. waifu2x-caffeによる画像の拡大とノイズ除去
  5. ffmpegにより拡大済み画像と音声を結合してmp4(H264)の動画に変換
  6. 次の動画があれば1から処理

作った理由

古いMVをwaifu2x-caffeとffmpegで4Kにして見るのが最近の個人的トレンドなのですが、とてもとてもとても処理に時間がかかる。
それなりに高くて新しいグラフィックボード(GTX1080)で3分の動画を4Kに変換すると2時間20分かかりました。
で、PCに張り付いて手動でコマンドを打つのは大変なので、自動化することにしました。

ホントはスクリプト作り込むなら慣れてるLinuxでやりたかったけど、それなりのグラボを積んだPCはWindows10で、理由があり別OSを入れられない状況。
プラスして、Windows 10のデフォルトシェルがPowerShellになるという話を見たばかりなのでPowerShellで作りました。

必要ソフトウェアと動作確認バージョン

スクリプト

本スクリプトで損害が発生しても当方は責任を負いません。(おやくそく)

###
# 設定

$movieWidth = 3840 # 変換後の横サイズ
$movieHeight = 2160 # 変換後の縦サイズ

$ffmpegPath = 'C:\ffmpeg\bin\ffmpeg.exe' # ffmpeg.exeのパス
$ffprobePath = 'C:\ffmpeg\bin\ffprobe.exe' # ffprobe.exeのパス
$waifu2xCaffeCui = 'C:\waifu2x-caffe\waifu2x-caffe-cui.exe' # waifu2x-caffe-cui.exeのパス

$inputFolder = 'D:\INPUT' # 入力ディレクトリ
$outputFolder = 'D:\OUTPUT' # 出力ディレクトリ
$fileType = ('*.mp4','*.avi') # 処理対象の拡張子
$tmpFolder = 'D:\tmp' # 作業用フォルダ(一時的に画像等を展開するため、それなりの容量が必要)

# Waifu2xCaffeのオプション
# オプションについては公開元をご参照ください
# https://github.com/lltcggie/waifu2x-caffe
$noiseScaleMode = 'noise_scale'
$noiseLevel = 1
$processType = 'gpu'
$cropSize = 512
$modelDir = 'models/upconv_7_anime_style_art_rgb'

##
# 以下処理

$tmpSourceImageFolder = $tmpFolder + '\movie2x\img_s'
$tmpSourceImageFiles = $tmpSourceImageFolder + '\img_%07d.jpg'
$tmpConvertImageFolder = $tmpFolder + '\movie2x\img_c'
$tmpConvertImageFiles = $tmpConvertImageFolder + '\img_%07d.png'
$tmpSourceWaveFile = $tmpFolder + '\movie2x\base.wav'

function RunProcess($exePathe, $argObj){
  $pinfo = New-Object System.Diagnostics.ProcessStartInfo
  $pinfo.RedirectStandardOutput = $true
  $pinfo.UseShellExecute = $false
  $p = New-Object System.Diagnostics.Process

  $pinfo.FileName = $exePathe
  $pinfo.Arguments = $argObj
  $p.StartInfo = $pinfo
  $p.Start() | Out-Null

  Write-Output $p
}

Remove-Item $tmpSourceImageFolder -recurse 2> $null
Remove-Item $tmpConvertImageFolder -recurse 2> $null
Remove-Item $tmpSourceWaveFile 2> $null

Get-ChildItem -Path $inputFolder -Recurse -Include $fileType | ForEach-Object {
  $date = Get-Date -Format "yyyy/MM/dd HH:mm"
  Write-Host "$date ファイル : $_ の処理を開始しました。" 

  ###
  # 動画の情報をffprobeで取得
  $expArg = '"' + $_.Fullname + '" -show_entries format -show_streams -print_format json'
  $process = RunProcess $ffprobePath $expArg

  $stdout = $process.StandardOutput.ReadToEnd()
  $json = $stdout | ConvertFrom-Json

  $fpsStrings = $json.streams[0].avg_frame_rate -split '/'
  $fps = $fpsStrings[0] / $fpsStrings[1]
  $sourceMovieWidth = $json.streams[0].width
  $sourceMovieHeight = $json.streams[0].height

  ##
  # 作業ディレクトリの作成
  New-Item $tmpSourceImageFolder -type directory -Force | Out-Null
  New-Item $tmpConvertImageFolder -type directory -Force | Out-Null

  ##
  #ffmpegにより音声/画像の分離
  $expArg = ' -i "' + $_.Fullname + '" -vn "' + $tmpSourceWaveFile

  $process = RunProcess $ffmpegPath $expArg
  $process.WaitForExit()

  $expArg = ' -i "' + $_.Fullname + '" -f image2 -vcodec mjpeg -qscale 1 -qmin 1 -qmax 1 "' + $tmpSourceImageFiles

  $process = RunProcess $ffmpegPath $expArg
  $process.WaitForExit()

  ##
  #widthとheightのどちらに合わせるべきか判定
  if($movieWidth / $sourceMovieWidth -lt $movieHeight / $sourceMovieHeight){
    $scaleString = ' --scale_width ' + $movieWidth
  }else{
    $scaleString = ' --scale_height ' + $movieHeight
  }

  ##
  # waifu2x-caffeによる画像の拡大とノイズ除去
  $expArg = ' -i ' + $tmpSourceImageFolder + ' -o ' + $tmpConvertImageFolder + ' --model_dir ' + $modelDir + ' -m ' + $noiseScaleMode + $scaleString +' --noise_level ' + $noiseLevel + ' -p ' + $processType + ' -c ' + $cropSize

  $process = RunProcess $waifu2xCaffeCui $expArg
  $process.WaitForExit()

  ##
  # ffmpegにより画像と音声を結合してmp4(H264)の動画に変換
  $expArg = ' -r ' + $fps + ' -i "' + $tmpConvertImageFiles + '" -i "' + $tmpSourceWaveFile + '" -f mp4 -vcodec libx264 -bufsize 20000k -maxrate 25000k -s ' + $movieWidth + 'x' + $movieHeight + ' -aspect ' + $sourceMovieWidth + ':' + $sourceMovieHeight + ' -pix_fmt yuv420p "' + $outputFolder + '\' + $_.Name + '"'

  $process = RunProcess $ffmpegPath $expArg
  $process.WaitForExit()

  Remove-Item $tmpSourceImageFolder -recurse 2> $null
  Remove-Item $tmpConvertImageFolder -recurse 2> $null
  Remove-Item $tmpSourceWaveFile 2> $null

  $date = Get-Date -Format "yyyy/MM/dd HH:mm"
  Write-Host "$date ファイル : $_ の処理が完了しました。" 
}