Nextcloud+CloudBeatsで出先から自宅の音楽データを再生 (7)他のスマホでのプレイリストの復元

以前、NextcloudというプライベートなオンラインストレージをRaspberry Pi上構築し、そこから参照するHDDに置いた音楽データにスマホからアクセスして聞く環境を構築していました。

dededemio.hatenablog.jp

構築以後、便利に使っていたのですが、以下の理由からNextcloudサーバごと引っ越しが必要になりました。

  • NextcloudのSNAP版・ARM版では、制限や不具合があり、スマホ写真の自動バックアップができなかった
  • iPhoneのパスワードがわからなくなり端末リセット→機種変更をしたため、新しいiPhoneにCloudbeatsをインストールしなおした

新しく構築したNextcloudから同様にHDDを外部ストレージとして見れるようにし、音楽は再生できるようになりました。しかし、プレイリストが失われてしまっていました。そこで、今回CloudBeatsのプレイリストの復元を行いました。

復元にあたり少しハマったところがあったので、忘備録的にメモしておきます。

この記事の目次は以下です。

前提条件

今回の復元は、以下の条件で行っています。

  • 有償のCloudBeats Syncサービス*1は利用していない
    • これを契約していた場合、ライブラリは複数デバイスで同期できるため、CloudBeatsアカウントでサインインすれば復旧できるはずです。
  • 元のCloudBeatsアプリから、バックアップファイルを書き出ししてある
    • プレイリスト復元のためには、アプリの設定(Settings)→バックアップと復元(Backup and Restore)→Create Backupで、.cbbackupファイルを出力し保存しておく必要があります。
    • これができていない場合、プレイリストの復旧は厳しいです。もし別で用意していたm3uファイルがあれば、以下記事の手順でそれをインポートすることはできます。

dededemio.hatenablog.jp

準備

まず、新Nextcloudで、旧Nextcloudと同じ場所に音楽ファイルを保存しておきます。口述しますが、もしファイルパスが異なる場合、復元にもうひと手間かかります。

また、バックアップした.cbbackupファイルを、新Nextcloudから参照できる場所に保存しておきます。

復元作業

以下の手順で復元を行います。

  • CloudBeatsアプリを立ち上げて、新Nextcloudサーバーを接続先に追加する
  • ライブラリ→スキャンから、新Nextcloudのうち音楽を取り込むフォルダを指定し、スキャン作業する
    • この記事を読んでいる方の多くはすでにCloudBeatsを利用されているのでわかると思うのですが、スキャンには結構時間がかかるので、作業時間を十分確保する必要があります。
  • Settings(設定)→バックアップと復元(Backup and Restore)→Restore from Backupで、新Nextcloudに保存した.cbbackupファイルを指定して、"復元する"を選択する
  • 曲情報、プレイリスト情報の読み込みが始まり、画面が閉じれば完了

基本的に、Nextcloud内の音楽ファイルのパス構造が変わっていなければ、これで復元できるはずです。復元されたプレイリストを開き曲を選択して、ファイルパスが正しいか、再生できるかを確認してください。

ファイルパスが異なり復元できない場合の対処

Nextcloud内の音楽ファイルのパス構造が変わっている場合、上記手順だけでは、うまく復元できません。具体的には、プレイリストは取り込めるけれども、再生できない、という状態になります。

取り込んだプレイリストから曲のプロパティを見ると、パスが"ownCloud/Nextcloud/<曲名>.<拡張子>"となってしまい、曲の入っているフォルダ構造が無くなり、再生できません。

まあプレイリストの曲順は情報として出てくるので、これを見ながら一曲ずつ指定しなおすこともできないことは無いですが、手間ですので、うまく復元できるようにします。

このために.cbbackupファイルを以下の手順で修正する必要があります。

  • 旧Nextcloudと新Nextcloudでパス構造がどう違うか確認する
    • 旧環境と同様に、新Nextcloudに接続したCloudBeatsアプリでも.cbbackupファイルをバックアップします
    • 旧環境と新環境の'.cbbackup'をそれぞれテキストエディタで開きます。
      • .cbbackupの中身は実質JSONで、最初に以下のようなアイテムが並びます。最初のitemsが各楽曲から取り込んだメタデータ、次のplaylistsがプレイリスト情報を示しているようです。
      • pathが音楽ファイルのパスを示します。\/remote.php\/webdav\/というのがNextcloudのルートを示しており、その下にディレクトリ構造が並ぶ形式になっています。
{
    "items": [
        {
            "account_id": "<ID>",
            "tag_trackNumber": 整数の数字,
            "tag_duration": 小数の数字,
            "tag_genre": "<ジャンル>",
            "path": "\/remote.php\/webdav\/data\/MUSIC\/<ジャンル名>\/<アーティスト名>\/<アルバム名>\/<ファイル名>.<拡張子>",
            "tag_diskNumber": 整数の数字,
            "key": "\/remote.php\/webdav\/data\/MUSIC\/<ジャンル名>\/<アーティスト名>\/<アルバム名>\/<ファイル名>.<拡張子>",
            "service": "owncloud",
            "tag_artist": "<アーティスト名>",
            "tag_album": "<アルバム名>",
            "tag_name": "<曲名>",
            "tag_albumArtist": "<アルバムアーティスト名>",
            "name": "<ファイル名>.<拡張子>"
        },
  • 最初の曲の"path"のディレクトリ構造を比較し、違いをメモしておきます
    • 自分の場合は、以下のような違いがありました。おそらくNextcloudの外部ストレージとして登録したルートが異なっていたのだと思います。
      • 旧Nextcloud: \/remote.php\/webdav\/Ubuntu\/data\/
      • 新Nextcloud: \/remote.php\/webdav\/data\/
  • .cbbackupファイルを修正する
    • 自分は、VSCodeで上記メモしたディレクトリ名を置換することで、修正しました。
    • .cbbackupファイルは、保有楽曲数によっては重たいので、テキストエディタだと開けず修正できない可能性があります。その場合は、以下のようなPythonスクリプトで置換することも可能です。
import os
# --- 設定項目 ---
input_file = 'cloudbeats.cbbackup'  # 元のファイル名
output_file = 'cloudbeats_fixed.cbbackup'  # 修復後のファイル名
# 置換したい文字列(エスケープされたスラッシュも含めて指定)
search_str = r'\/remote.php\/webdav\/Ubuntu\/data\/'
replace_str = r'\/remote.php\/webdav\/data\/'
def fix_cloudbeats_backup():
    if not os.path.exists(input_file):
        print(f"エラー: {input_file} が見つかりません。")
        return
    print(f"処理を開始します: {input_file} -> {output_file}")
    try:
        with open(input_file, 'r', encoding='utf-8') as f_in:
            with open(output_file, 'w', encoding='utf-8') as f_out:
                for line in f_in:
                    # 文字列を置換して書き込み
                    new_line = line.replace(search_str, replace_str)
                    f_out.write(new_line)
        print("完了しました!新しいファイルをCloudBeatsで読み込んでください。")
    except Exception as e:
        print(f"実行中にエラーが発生しました: {e}")
if __name__ == "__main__":
    fix_cloudbeats_backup()

この作業をしたのち、前の手順通りにCloudBeatsアプリから再度復元すると、正しく復元でき、曲が再生できるようになります。

*1:\1,500/年で、複数デバイス間のプレイリスト・ライブラリの同期、音楽データのバックアップと復元が可能