VLC media player のプレイリストファイルから動画に埋め込むチャプターファイルを生成する CopyQ スクリプト

f:id:dot-harley:20200110233155j:plain

以前 VLC media player のカスタムブックマークを利用してお気に入りのシーンを保存する方法を記事にしました。

VLC media player のカスタムブックマークを利用する - In my mind

ですが、これだと動画ファイルとともにプレイリストファイルも管理しなければなりません。動画のファイル名を変更したらプレイリストファイルの中身も書き換えなきゃいけないとか面倒です。

やっぱり動画にチャプターを埋め込みたい。

そこで VLC media player のプレイリストファイルからチャプターファイルを生成する CopyQ スクリプトを書いてみました。

特徴

  • VLC media player のプレイリストファイルから動画に埋め込むチャプターファイルを生成します。

  • プレイリストに複数の動画が登録されている場合、カスタムブックマークが登録されている動画すべてのチャプターファイルを生成します。

  • 生成されるチャプターファイルは Nero 形式。mkv や mp4 に埋め込むことが出来ます。

  • 童画の初め 00:00:00.000 時点にカスタムブックマークが登録されていない場合は自動でチャプターが追加されます。

  • 「もっとスマートなやり方があるよ」という方はぜひコメント欄にお願いします。

免責事項

無保証です。このスクリプトを使用して何らかの損害が発生したとしても、作者は責任を負いません。

不具合の報告はコメント欄にお願いします。直せるかどうか分かりませんが。。。

コード

[Command]
Automatic=true
Command="
    copyq:
    // \x79d2\x3092\x6642\xff1a\x5206\xff1a\x79d2\x306b\x5909\x63db\x3059\x308b\x95a2\x6570
    function toHms(t) {
      var hms = \"\";
      var h = t / 3600 | 0;
      var m = t % 3600 / 60 | 0;
      var s = t % 60;
    
      hms = padZero(h) + \":\" + padZero(m) + \":\" + padZero(s);
    
      return hms;
    
      function padZero(v) {
        return (\"0\" + v).slice(-2)
      }
    }
    
    // xspf \x30d5\x30a1\x30a4\x30eb\x306e\x30d1\x30b9\x3092\x53d6\x5f97
    var xspfLocation = str(clipboard('text/plain'))
    
    // xspf \x30d5\x30a1\x30a4\x30eb\x306e\x5185\x5bb9\x3092\x8aad\x307f\x3053\x3080
    var f = new File (xspfLocation)
    if ( ! f . openReadOnly ())
      throw 'Failed to open the file: ' + f . errorString ()
    var bytes = f . readAll ();
    if( ! str(bytes).match(/xmlns:vlc=\\\"http:\\/\\/www\\.videolan\\.org\\/vlc\\/playlist/)){
      popup('This is NOT VLC playlist file!')
    }
    
    // <track> \x3092\x914d\x5217\x306b\x683c\x7d0d
    var tracks = str(bytes).match( /<track>[\\s\\S]+?<\\/track>/g );
    
    for (r in tracks){
      if(! tracks[r].match(/<vlc:option>bookmarks={/ ))
        continue
      // \x51fa\x529b\x5148
      var location = tracks[r].replace(/^[\\s\\S]*?<location>file:\\/\\/(.+?)<\\/location>[\\s\\S]*$/ , '$1.chapter.txt')
      // \x30ab\x30b9\x30bf\x30e0\x30d6\x30c3\x30af\x30de\x30fc\x30af\x3092\x53d6\x5f97
      var bookmarks = tracks[r].match(/\\{name=.+?,time=.+?\\}/g );
      var bookmarksArry = [];
      for(s in bookmarks){
        bookmarksArry[s] = {}
        bookmarksArry[s].name = bookmarks[s].replace(/^.*?name=(.+?),.*$/ , '$1')
        bookmarksArry[s].time = bookmarks[s].replace(/^.*?time=(\\d+?)\\.\\d*\\}/ , '$1')
        bookmarksArry[s].frame = bookmarks[s].replace(/^.*?time=\\d+?\\.(\\d*)\\}/ , '$1')
      }  
      // \x30ab\x30b9\x30bf\x30e0\x30d6\x30c3\x30af\x30de\x30fc\x30af\x3092\x6642\x9593\x9806\x306b\x30bd\x30fc\x30c8
      function compareFunc(a, b){
        return a.time - b.time;
      }
      bookmarksArry.sort(compareFunc);
      // \x30c1\x30e3\x30d7\x30bf\x30fc\x30d5\x30a1\x30a4\x30eb\x306e\x5185\x5bb9\x3092\x751f\x6210
      var chapter = ''
      var m = 0
      if(bookmarksArry[0].time != 0 && bookmarksArry[0].frame != 0){
        chapter = 'CHAPTER01=00:00:00.000\\nCHAPTER01NAME=Start\\n'
        m = 1
      }
      for(s in bookmarksArry){
        n = Number(s) + 1 + m;
        chapter += 'CHAPTER' + ('0' + n).slice(-2) + '=' + toHms(bookmarksArry[s].time) + '.' + bookmarksArry[s].frame + '\\n'
          + 'CHAPTER' + ('0' + n).slice(-2) + 'NAME=' + bookmarksArry[s].name + '\\n'
      }
      add(chapter)
      //  \x30c1\x30e3\x30d7\x30bf\x30fc\x30d5\x30a1\x30a4\x30eb\x3092\x66f8\x304d\x51fa\x3059
      var g = new File ( decodeURIComponent(location) )
      if ( ! g . openWriteOnly () || g . write ( chapter ) == - 1 )
        throw 'Failed to save the file: ' + g . errorString ()
      // Always flush the data and close the file,
      // before opening the file in other application.
      g . close ()
    }"
Icon=\xf008
Input=text/plain
Match=\\.xspf$
Name=VLC playlist.xspf -> chapter.txt

使い方

準備

あらかじめ以下の記事を参考に、スクリプトを登録しておきます。

CopyQ に共有スクリプトを追加する方法 - In my mind

あらかじめ CopyQ を起動しておきます。

動画とそのプレイリストファイルを用意します。

今回は動画「Cat-2879.mp4」とプレイリストファイル「Cat-2879.xspf」を用意しました。

チャプターファイルを生成

プレイリストファイル「Cat-2879.xspf」をクリップボードにコピーするだけです。

プレイリストファイルをクリップボードにコピー

ほどなくチャプターファイルが生成されます。

ファイル名は「動画名 + .chapter.txt」となります。今回は「Cat-2879.mp4.chapter.txt」ですね。

チャプターファイルが生成された

動画にチャプターを埋め込む

今回は MkvToolnix を使って動画にチャプターを埋め込みます。

MkvToolnix で動画ファイルを開きます。

MkvToolnix で動画を開く

  1. 出力タブに移ります。

  2. さきほど生成されたチャプターファイルを選択。

  3. 出力先とファイル名を指定します。

  4. 「Start multiplexing」で即時出力するなり「ジョブキューに追加」して後からまとめて出力するなりお好きなように。

チャプターを埋め込む

確認

出来上がった動画ファイルを VLC media player で再生してみます。

メニュー > 再生 > チャプター から好きなシーンにジャンプできるようになりました。

チャプターが埋め込まれた

参考

MP4のチャプターファイルについて: Take it eazy!!


アイキャッチ画像素材提供:A MacBook with lines of code on its screen on a busy desk photo – Free Computer Image on Unsplash