ダイナミックプレイリストの作成

念願だったダイナミックプレイリストの作成ができました。
このプレイリストはフロントページに設置している動画再生に使用しているものです。

変更前:

Viewsページにあるフィールドスタイルで"行スタイルテンプレート"をカスタマイズすることで目的のMRSSプレイリストをダイナミックに生成し、そのプレイリストページのソースコードから追加分をコピーしプレイリストファイルにペーストしてスタティックプレイリストを作成していました。

変更後:

Viewsフィードにあるテキストスタイルで"スタイルのアウトプットテンプレート"をカスタマイズすることにより、目的のMRSSプレイリストをダイナミックに生成します。

プレイヤーはJW FLV Media Playerを使用していますが、Version4.xまではXSPFフォーマットのプレイリストを使用していました。
XSPFフォーマットだとXSPFプレイリストモジュールが使えそうですが、Drupal 6.xではどうも機能していないような感じ(Viewsの知識もあまりなかったのでよくわからない状態)でした。
Drupal6.xのViews2での動作確認はしていないという一言もありましたので・・・
そのため当初はプレイリストを自作していました。
Media PlayerをVersion5.xに置き換えると今まで使用していたXSPFフォーマットのプレイリストではなぜか再生ができず、諦めてMRSSフォーマットに切り替えました。
MRSSフォーマットはMedia用のRSSフォーマットですので、ファイルサイズやコンテンツの時間などさらに詳細なメディアの情報が記述できます。
せっかく記述できるのだからと思ってfilesize,durationをプレイリストに追加したのはよかったのですが、今使っているMedia Playerではdurationが使用できるだけです。
動画の編集に2~3時間、エンコードに約1時間、アップロード(記事投稿)に10分~1時間(攻城戦の内容をNC部ログに投稿する場合)、そのあとにプレイリストをとなったときにこれらの数値を取得する手作業が苦痛でしかありませんでした。
変更前の方法ではfilesizeとdurationの数値を自動で取得することができただけでも負担が減りました。
このときのViewsモジュールの理解度が浅かったのが原因ですけども、とりあえずなんとかなるレベルでした。

変更後は、Views2を使う機会も増え、Views2自体の理解も以前より深まりました。
ddblockを利用していた際に導入していたViewsのbonusパックモジュールの機能により、フィードでTXTファイルを作成するようにしました。
XMLファイルを作成するとタグが付加されてしまうため、Viewsテンプレートをいくつも用意しなけれいけなくなると判断したためです。

前々からフィードでトライはしていたのですが、ページで作成した場合とフィードで作成する場合とではViewsのテンプレートが異なるため、使用できる変数も異なりそれがネックでなかなかうまく作りこめませんでした。
諦めてviewsページを作成するほうに逃げていたのですが、あれから1年くらい経過した今、ようやく完成までたどり着けました。

 

関連モジュール

 

fiflefield 6.x-3.10 filefield metaを使用
getid3を使用してメディアファイルの情報を取得する
getid3() 6.x-1.4 getID3() PHP libraryが必要
fifefieldでmimetype、ID3情報、ビットレートなどを取得する
mimedetect 6.x-1.3 PHP fileinfo拡張API、UNIXのfileコマンドや拡張子からmimetypeを取得する。
※fileinfoが使える環境もしくはfileコマンドが使える環境が必要
views 6.x-2.12 readmeに推奨モジュールの記載あり
Views Bonus Pack 6.x-1.1 panels,feed-page,exportを追加する
views exportでcsv,doc,txt,xmlファイル出力をサポート
Views Bulk Operations 6.x-1.10 一括処理のアクションを追加できる
content construction kit 6.x-2.9 filefieldを使用するために必要
コンテンツ情報
コンテンツタイプ movies
動画アップロード用ファイルフィールド video_files
カバー画像アップロード用ファイルフィールド image_files
リンクURL用プレーンテキストファイルフィールド link_url
MRSSフォーマットの雛形

※itemタグで囲まれた部分がmoviesコンテンツのノードの数だけ繰り返されればOKです。
※media:credit roleの値は固定値にしてあります。投稿ユーザ名でもよさそうです。

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
 <channel>
  <item>
    <title>[title]</title>
    <media:credit role="author">by SHIBATA.K</media:credit>
    <description>[body]</description>
    <media:content url="[field_video_files_fid]" type="[filemime]" duration="[duration]" fileSize="[filesize]" />
    <media:thumbnail url="[filed_image_files_fid]" />
    <link>[field_link_url_value]</link>
  </item>
 </channel>
</rss>
プレイリスト用views名:Lineage2_playlist

※リレーションシップを設定しないとDuration,MimeType,ファイルサイズの値が取得できません。

Lineage2_playlistのエクスポート
$view = new view;
$view->name = 'Lineage2_playlist';
$view->description = 'Lineage2 動画用のプレイリスト';
$view->tag = 'lineage2_playlist';
$view->view_php = '';
$view->base_table = 'node';
$view->is_cacheable = FALSE;
$view->api_version = 2;
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */
$handler = $view->new_display('default', 'デフォルト', 'default');
$handler->override_option('relationships', array(
  'field_video_files_fid' => array(
    'label' => 'video_files',
    'required' => 0,
    'delta' => -1,
    'id' => 'field_video_files_fid',
    'table' => 'node_data_field_video_files',
    'field' => 'field_video_files_fid',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
    'relationship' => 'none',
  ),
));
$handler->override_option('fields', array(
  'title' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '<title>[title]</title>',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_node' => 0,
    'exclude' => 0,
    'id' => 'title',
    'table' => 'node',
    'field' => 'title',
    'relationship' => 'none',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
  ),
  'body' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 1,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'exclude' => 0,
    'id' => 'body',
    'table' => 'node_revisions',
    'field' => 'body',
    'relationship' => 'none',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
  ),
  'field_link_url_value' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 1,
    'empty_zero' => 0,
    'link_to_node' => 0,
    'label_type' => 'none',
    'format' => 'plain',
    'multiple' => array(
      'group' => TRUE,
      'multiple_number' => '',
      'multiple_from' => '',
      'multiple_reversed' => FALSE,
    ),
    'exclude' => 0,
    'id' => 'field_link_url_value',
    'table' => 'node_data_field_link_url',
    'field' => 'field_link_url_value',
    'relationship' => 'none',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
  ),
  'field_video_files_fid' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_node' => 0,
    'label_type' => 'none',
    'format' => 'url_plain',
    'multiple' => array(
      'group' => TRUE,
      'multiple_number' => '',
      'multiple_from' => '',
      'multiple_reversed' => FALSE,
    ),
    'exclude' => 0,
    'id' => 'field_video_files_fid',
    'table' => 'node_data_field_video_files',
    'field' => 'field_video_files_fid',
    'relationship' => 'none',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
  ),
  'duration' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'set_precision' => FALSE,
    'precision' => 0,
    'decimal' => '.',
    'prefix' => '',
    'suffix' => '',
    'format' => 'default',
    'exclude' => 0,
    'id' => 'duration',
    'table' => 'filefield_meta',
    'field' => 'duration',
    'relationship' => 'field_video_files_fid',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
  ),
  'filemime' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_file' => 0,
    'exclude' => 0,
    'id' => 'filemime',
    'table' => 'files',
    'field' => 'filemime',
    'relationship' => 'field_video_files_fid',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
  ),
  'filesize' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'file_size_display' => 'bytes',
    'exclude' => 0,
    'id' => 'filesize',
    'table' => 'files',
    'field' => 'filesize',
    'relationship' => 'field_video_files_fid',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
  ),
  'field_image_files_fid' => array(
    'label' => '',
    'alter' => array(
      'alter_text' => 0,
      'text' => '',
      'make_link' => 0,
      'path' => '',
      'link_class' => '',
      'alt' => '',
      'prefix' => '',
      'suffix' => '',
      'target' => '',
      'help' => '',
      'trim' => 0,
      'max_length' => '',
      'word_boundary' => 1,
      'ellipsis' => 1,
      'html' => 0,
      'strip_tags' => 0,
    ),
    'empty' => '',
    'hide_empty' => 0,
    'empty_zero' => 0,
    'link_to_node' => 0,
    'label_type' => 'none',
    'format' => 'url_plain',
    'multiple' => array(
      'group' => TRUE,
      'multiple_number' => '',
      'multiple_from' => '',
      'multiple_reversed' => FALSE,
    ),
    'exclude' => 0,
    'id' => 'field_image_files_fid',
    'table' => 'node_data_field_image_files',
    'field' => 'field_image_files_fid',
    'relationship' => 'none',
    'override' => array(
      'button' => '上書き(オーバーライド)',
    ),
  ),
));
$handler->override_option('sorts', array(
  'created' => array(
    'order' => 'DESC',
    'granularity' => 'second',
    'id' => 'created',
    'table' => 'node',
    'field' => 'created',
    'relationship' => 'none',
  ),
));
$handler->override_option('filters', array(
  'type' => array(
    'operator' => 'in',
    'value' => array(
      'movies' => 'movies',
    ),
    'group' => '0',
    'exposed' => FALSE,
    'expose' => array(
      'operator' => FALSE,
      'label' => '',
    ),
    'id' => 'type',
    'table' => 'node',
    'field' => 'type',
    'relationship' => 'none',
  ),
  'status' => array(
    'operator' => '=',
    'value' => '1',
    'group' => '0',
    'exposed' => FALSE,
    'expose' => array(
      'operator' => FALSE,
      'label' => '',
    ),
    'id' => 'status',
    'table' => 'node',
    'field' => 'status',
    'relationship' => 'none',
  ),
));
$handler->override_option('access', array(
  'type' => 'none',
));
$handler->override_option('cache', array(
  'type' => 'none',
));
$handler->override_option('title', 'lineage2_playlist');
$handler->override_option('header_format', '2');
$handler->override_option('header_empty', 1);
$handler->override_option('footer_format', '2');
$handler->override_option('footer_empty', 1);
$handler->override_option('items_per_page', 0);
$handler->override_option('row_options', array(
  'inline' => array(),
  'separator' => '',
  'hide_empty' => 0,
));
$handler->override_option('exposed_block', TRUE);
$handler = $view->new_display('feed', 'フィード', 'feed_1');
$handler->override_option('style_plugin', 'views_txt');
$handler->override_option('style_options', array(
  'mission_description' => FALSE,
  'description' => '',
  'attach_text' => 'Plain Text Document',
  'provide_file' => 0,
  'filename' => 'view-%view.txt',
  'parent_sort' => 0,
));
$handler->override_option('row_plugin', '');
$handler->override_option('row_options', array());
$handler->override_option('path', 'lineage2_playlist.xml');
$handler->override_option('menu', array(
  'type' => 'none',
  'title' => '',
  'description' => '',
  'weight' => 0,
  'name' => 'navigation',
));
$handler->override_option('tab_options', array(
  'type' => 'none',
  'title' => '',
  'description' => '',
  'weight' => 0,
  'name' => 'navigation',
));
$handler->override_option('displays', array());
$handler->override_option('sitename_title', 0);
viewsテンプレートファイル:views-bonus-export-txt--Lineage2-playlist.tpl.php

※使用しているテーマディレクトリ直下にファイルを作成します。

<?php print '<?xml version="1.0" encoding="utf-8"?>';?><?php print "\n" ;?>
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
 <channel>
<?php
// $Id: views-bonus-export-txt.tpl.php,v 1.1 2008/10/08 05:50:10 neclimdul Exp $
/**
 * @file views-view-table.tpl.php
 * Template to display a view as a table.
 *
 * - $title : The title of this group of rows.  May be empty.
 * - $rows: An array of row items. Each row is an array of content
 *   keyed by field ID.
 * - $header: an array of haeaders(labels) for fields.
 * - $themed_rows: a array of rows with themed fields.
 * @ingroup views_templates
 */

foreach ($themed_rows as $count => $row):
 foreach ($row as $field => $content):
?>
<?php 
	switch ($field){
		case title:
			$title=$content;
			break;
		case body:
			$body=$content;
			break;
      		case field_link_url_value:
      			$link_url=$content;
      			break;
      		case field_video_files_fid:
      			$video_url=$content;
      			break;
      		case duration:
      			$duration=$content;
      			break;
      		case filemime:
      			$file_mime=$content;
      			break;
      		case filesize:
      			$file_size=$content;
      			break;
      		case field_image_files_fid:
      	    		$image_url=$content;
      	    		break;
      		default:
      			break;
	}
?>
 <?php endforeach; ?>
 <item>
  <title><?php print $title;?></title>
  <description><?php print $body;?></description>
  <media:credit role="author">by SHIBATA.K</media:credit>
  <media:content url="<?php print $video_url;?>" type="<?php print $file_mime;?>" duration="<?php print $duration;?>" fileSize="<?php print $file_size;?>" />
  <media:thumbnail url="<?php print $image_url;?>" />
  <link><?php print $link_url;?></link>
 </item>
<?php endforeach; ?>
 </channel>
</rss>
Views画面でのテンプレートの設定

各フィールドの表示でrewriteを使って書き換えればいけそうですが、それでもテンプレートファイルを編集しなければどうしようもないので、それならば全部テンプレートファイルでやったほうがよいかということでこうなりました。
タイトルとビデオファイルだけのプレイリストであれば、audioプレイリストの作成を手本に、XML出力で実現できると思います。
もっとシンプルな方法があるのかもしれませんが今はこんな感じでとりあえずダイナミックに生成できています。
スタティックの場合と表示速度を比べるとワンテンポ遅れているようにも感じますが、許容範囲かなぁと思います。

Drupalバージョン

Drupal 6.x モジュール