ffmpegのコンパイル



svnから最新版をダウンロードして、コンパイルする度に嵌るので、ブログでインストール方法を管理することにしました。

ffmpegの用途は、拡張子がmpg/mpeg/mp4/m4v/avi/mov/wmv/3gpである動画ファイルをflvフォーマットの動画に変換することです。

対象となる動作環境はCentOS 5です。

[gcc]
# yum install gcc

[mp3lame]
http://downloads.sourceforge.net/lame/
# tar zxvf lame-XXX.tar.gz
# cd lame-XXX
# ./configure
# make
# make install

[git]
# wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-X.noarch.rpm
# rpm -ivh epel-release-5-X.noarch.rpm
# yum install git

[opencore-amr]
# git clone git://opencore-amr.git.sourceforge.net/gitroot/opencore-amr
# cd opencore-amr
# make
# make install

[automake]
# yum install automake

[libtool]
# yum install libtool

[gcc-c++]
# yum install gcc-c++

[faac]
http://sourceforge.net/project/showfiles.php?group_id=704
# tar zxvf faac-X.X.tar.gz
# cd faac-X.X
# sh bootstrap
# ./configure
# make
# make install

[faad2]
http://sourceforge.net/project/showfiles.php?group_id=704
# tar zxvf faad2-X.X.tar.gz
# cd faad2-X.X/
# sh bootstrap
# ./configure
# make
# make install

[nasm]
# yum -y install nasm

[yasm]
http://www.tortall.net/projects/yasm/releases/
# tar zxvf yasm-X.X.X.tar.gz
# cd yasm-X.X.X
# ./configure
# make
# make install

[x264]
http://downloads.videolan.org/pub/videolan/x264/snapshots/
# tar jxvf x264-snapshot-YYYYMMDD-VVVV.tar.bz2
# cd x264-snapshot-YYYYMMDD-VVVV
# ./configure –enable-shared
# make
# make install

[xvid]
http://www.xvid.org/downloads.html
# tar xvzf xvidcore-X.X.X.tar.gz
# cd xvidcore-X.X.X/build/generic
# ./configure
# make
# make install

[a52]
http://liba52.sourceforge.net/downloads.html
# tar zxvf a52dec-X.X.X.tar.gz
# cd a52dec-X.X.X
# sh bootstrap
# ./configure
# make
# make install

[ogg]
# yum install libogg-devel

[vorbis]
# yum install libvorbis-devel

[subversion]
# yum install subversion

[ffmpeg]
# svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
# cd ffmpeg/libavcodec
# patch -p1 < ffmpeg.patch
# cd ../
# ./configure –enable-gpl –enable-libmp3lame –enable-libxvid –disable-ffplay –disable-ffserver –enable-libfaac –enable-libfaad –enable-libx264 –enable-shared –enable-nonfree –enable-libvorbis –enable-pthreads –enable-libopencore-amrnb –enable-libopencore-amrwb –enable-version3 –disable-demuxer=v4l –disable-demuxer=v4l2 –disable-indev=v4l
# make
# make install

最後に変換テストです。

$ setenv LD_LIBRARY_PATH /usr/local/lib
$ ffmpeg -y -i test.avi -f flv -vcodec flv -acodec libmp3lame -r 25 -b 1000k -ab 64k -ar 44100 -s qvga test.flv

Subversionによるソースコード管理

ソースコードを管理する必要が出てきたので、Subversionを利用することにしました。
そこで、基本的なことを勉強するために、

を購入し、熟読しました。読むまでは、

  • 複数のプログラマが同時に更新した場合はどうなるのだろうか?
  • バイナリファイルでも利用できるのだろうか?

等の疑問がありましたが、これらについてすべて丁寧に解説されていました。
早速Cent OS 4.5に最新版をソースからコンパイルしてインストールしました。

Zend FrameworkのHTTPリクエストオブジェクト

開発から遠ざかっていたので、久々の投稿になりますが、今回は新たにZend Frameworkを使って開発することになりました。いきなりマニュアルを読むのは退屈なので、まずは、

あるいは、

を読み、後ほどプログラマ向けリファレンスガイドを読むことにしました。
そこで、HTTPリクエストオブジェクトでいきなり躓いたので、メモしておきます。上記の書籍によれば、HTTPリクエストオブジェクトでは、

$_GET / $_POST

は使わず、それぞれ

getQuery() / getPost()

を使うルールことになっているそうなのだが、実際に、

$request = $this->getRequest();
$foo = $request->getQuery('foo');

として、

http://www.example.com/index/index/foo/1/bar/1

にアクセスしても、データは取得できませんでした。もちろん、

http://www.example.com/index/index?foo=1&bar=1

にアクセスすれば、データは取得できます。やむを得ず、

$foo = $this->_getParam('foo');
$bar = $this->_getParam('bar');

としてひとまず無事解決しました。(ちなみに面倒だったので、Postは試していません。今回はGetのみです。ごめんなさい。)そこで、いろいろと実験してみてわかったのは、以下の通りです。

  • これはNG
  • $foo = $_GET['foo'];
  • これらはOK
  • $request = $this->getRequest();
    $foo = $request->getParam('foo');
     
    // あるいは
     
    $foo = $this->_getParam('foo');

Amazon with Symfony

YouTube with Symfonyと同様、PEARを使わずにAmazon ECS Webサービスをsymfonyで利用する方法をメモしておきます。

<?php
class bookComponents extends sfComponents
{
  public function executeDefault()
  {
    $apikey = "YOUR_API_KEI";
    $asocid = "YOUR_ASSOCIATE_ID";
 
    $url = sfConfig::get('app_book_url') . "Service=AWSECommerceService&AWSAccessKeyId=" . $apikey . "&AssociateTag=" . $asocid
           . "&ResponseGroup=Large&Operation=ItemSearch&SearchIndex=Books&locale=JP&Sort=daterank&Version=2007-05-14&BrowseNode=499986";
    $res = file_get_contents($url);
    $xml = simplexml_load_string($res);
 
    $this->books = array();
    foreach ($xml->Items->Item as $item) {
      $book_data = (array)$item;
      $isbn = $book_data['ASIN'];
      $url = $book_data['DetailPageURL'];
      $book_attr = (array)$book_data['ItemAttributes'];
      if (isset($book_attr['Author'])) {
        if (is_array($book_attr['Author'])) {
          $author = htmlspecialchars($book_attr['Author'][0], ENT_QUOTES);
        } else {
          $author = htmlspecialchars($book_attr['Author'], ENT_QUOTES);
        }
      } else {
        $author = "";
      }
      $title = htmlspecialchars($book_attr['Title'], ENT_QUOTES);
      $date = $book_attr['PublicationDate'];
      if (isset($book_attr['Publisher'])) {
        $publisher = htmlspecialchars($book_attr['Publisher'], ENT_QUOTES);
      } else {
        $publisher = "";
      }
      $book_price = (array)$book_attr['ListPrice'];
      $price = $book_price['Amount'];
      if (isset($book_data['SmallImage'])) {
        $book_image = (array)$book_data['SmallImage'];
        $image_url = $book_image['URL'];
      } else {
        $image_url = "";
      }
 
      $book_items = array('isbn'=>$isbn, 'url'=>$url, 'title'=>$title, 'author'=>$author, 'price'=>$price, 'publisher'=>$publisher, 'date'=>$date, 'thumbnail_url'=>$image_url);
      array_push($this->books, $book_items);
    }
  }
}
?>

このコードはドッグランファン(廃止)で利用しています。

WordPressエントリ内の<P>タグを無効化

WordPressのエントリ内にjavascriptを埋め込み、document.writeでテキスト表示させたかったのですが、デフォルトのままではエントリの行単位に挿入される<p>タグの影響で、document.writeが動作しませんでした。

そこで、

タグの挿入を無効にするにはどうすればいいのかをネットで調べていると、下記のサイトにヒントがありました。

iDeasilo

wpautop($pee, $br = 1)
空行で囲まれたテキストを段落とみなしてそれぞれ <p></p> タグで囲んでテキスト全体を返す。

そこで、
“wp-includes/default-filters.php” の 121行目(V2.0.9)や123行目(V2.2)あたりの

add_filter('the_content', 'wpautop');

をコメントアウトすると、<p></p>タグは挿入されなくなりました。

もしExcerptの<p></p>タグも無効にしたいのであれば、同ファイルの

add_filter('the_excerpt', 'wpautop');

をコメントアウトすれば良いような気がします。(未検証)

Last.fm API

先日、近所の本屋に行った時に、

が平積みされていたので、手にとってパラパラと流し読みしていると、Last.fmのWebサービスについて書かれているだがあり、Webサービス用のAPIが公開されていることを知りました。

Web APIの詳細はAudioscrobbler Web Services APIにあります。早速、洋楽歌詞@Tube365に取り込めそうなAPIを探してみたところ、
①Related Artists(アーティストのレコメンデーション)
②TopTracks(人気曲)
がありました。

これらを実装した方法をメモしておきます。以下はTopTracks(人気曲)の取得方法です。

<?php
function getTopTracks($artist_name) {
  $base_url = "http://ws.audioscrobbler.com/1.0/artist/";
  $res = file_get_contents($base_url . $artist_name . "/toptracks.xml") or die("HTML取得エラー\n");
  $xml = simplexml_load_string($res);
  $xml_items = $xml->xpath('//track');
 
  $popular_songs = array();
  foreach ($xml_items as $xml_item) {
    $track_data = (array)$xml_item;
    array_push($popular_songs, $track_data['name']);
  }
  return $popular_songs;
}
?>

Related Artistsにする場合は、「/toptracks.xml」を「/similar.xml」に置き換え、xpath(’//track’)をxpath(’//artist’)に置き換えればOKです。(本来ならば、変数名も変えるべきですけど)

ついでに、サンプルレスポンスをリンクしておきます。

TopTracks
Related Artists

mod_rewriteによる静的URL

洋楽歌詞@Tube365では、PHPによる動的URLでプログラムを組んだのですが、検索エンジン最適化(Search Engine Optimization:SEO)の観点ではよろしくないとのことで、Apacheのmod_rewrite機能を利用して、静的URLへの変換にチャレンジしてみました。

多くの方が既に詳細な説明文を公開されているので、こここでは備忘録程度にしています。

.htaccessに下記のように記載すると、

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^param1-([a-z]+)$ index.php?param1=$1 [QSA,L]
RewriteRule ^param1-([a-z]+)/param2-([0-9]+)$ index.php?param1=$1&param2=$2 [QSA,L]

http://hogehoge.com/index.php?param1=foo&param2=bar

でアクセスしていたところを、

http://hogehoge.com/param1-foo/param2-bar

でアクセスができるようになります。

QSAフラグを付けると、

http://hogehoge.com/param1-foo/param2-bar&param3=boo

とアクセスした場合でも、正しく

http://hogehoge.com/index.php?param1=foo&param2=bar&param3=boo

と変換してくれます。

XREAサーバでSymfonyを動かした場合の問題

当然ながら本番環境では、

“/myproject/apps/myapp/config/settings.yml”

prod:
  .settings:
    cache    on

“/myproject/apps/config/cache.yml”

default:
  enabled:     on
  with_layout: false
  lifetime:    86400

としてキャッシュ機能を有効にし、レスポンスの向上を図りたいわけですが、

“/myproject/apps/myapp/modules/mymodule/template/searchSuccess.php”

<?php echo form_tag('@search', 'method=get') ?>
<?php echo input_tag('query', htmlspecialchars($sf_params->get('query'), ENT_QUOTES), array('style' => 'width: 150px')) ?>&nbsp<?php echo submit_tag('検索') ?>
</form>

のように、GETメソッドを利用したformを含むtemplateをキャッシュすると、

$sf_params->get('query')

で取得したvalueがなぜか表示されません。ちなみに、POSTメソッドを使った場合は問題ありませんでした。

対処療法的ですが、

“/myproject/apps/myapp/modules/mymodule/config/cache.yml

search:
  disabled:    off

として、formのテンプレートはキャッシュをOffにすれば、正常に動作します。
根本的な解決をするためには、symfonyのコードを読まないと、なんともできないですね。でも、コード量は半端じゃなく膨大ですから、気合いを入れて取りかからないと、時間の無駄になってしまいそう。暇を見つけて、チャレンジしてみたいと思います。

symfonyでGoogle Map(グーグルマップ)を使う

SymfonyでGoogleMapを使う方法を紹介します。いろいろ方法はあるのだろうが、一番手っ取り早くて、JavaScriptを書かなくても利用できる方法を紹介します。
具体的には、PHP Google MAP APIクラスライブラリを利用します。
PHP GoogleMapAPIでクラスライブラリが公開されており、これをダウンロードしてSymfonyの/myproject/apps/myapp/lib/におき、該当するモジュールのaction.calss.phpでrequireしてパラメータをセットします。
例えば、下記のような感じです。各行の意味はだいたいわかると思いますが、詳細はクラスライブラリのソース内に記載(英語)がありますので、そちらを参照してください。

“actions.class.php”

require('GoogleMapAPI.class.php');
 
$this->map = new GoogleMapAPI();
$this->map->setHeight('400px');
$this->map->setWidth('400px');
$this->map->enableMapControls();
$this->map->enableZoomEncompass();
$this->map->enableOverviewControl();
$this->map->enableSidebar();
$this->map->setBrowserAlert(
          'お使いのブラウザでは地図を表示することができません。'
          .'Internet Explorer 6.0以降か、'
          .'Firefox 1.0以降をおすすめします。');
$this->map->setJSAlert('お使いのブラウザではJavascript'
          .'に対応していないか、Javascript がオフになっています。'
          .'Javascript の動くブラウザでないと地図は表示できません');
$this->map->setInfoWindowTrigger('mouseclick');
$this->map->disableDirections();
$this->map->addMarkerByCoords($lat, $lng, $title, $html);

また、テンプレートファイルには表示するためのコードを記述します。

“indexSuccess.php”

<?php $map->printSidebar() ?>
<?php $map->printMap() ?>

さらに、当然のことながら、Google MAPはJavaScriptを使っているので、HTMLのheadにJavaScriiptのパス設定が必要です。

“template.php”

<?php $map->printHeaderJS() ?>
<?php $map->printMapJS() ?>

実際に実装した結果は以下です。

ドッグランファンサイト

XREAサーバへのsymfonyのインストール方法

symfonyで開発したWebアプリケーションをXREAサーバにインストールした時の作業内容をメモしておきます。
symfonyフレームワーク テスト置き場に記載されている手順を参考にしました。

1.pearのインストール
phpディレクトリに作成

$mkdir ~/php

http://pear.php.net/go-pearの内容をコピーして~/go-pear.phpとして保存して実行

1. Installation prefix           : /usr/local
 2. Binaries directory            : $prefix/bin
 3. PHP code directory ($php_dir) : $prefix/lib/php
 4. Documentation base directory  : $php_dir/docs
 5. Data base directory           : $php_dir/data
 6. Tests base directory          : $php_dir/tests
 7. Temporary files directory     : $prefix/temp

1-7, 'all' or Enter to continue:

1を選択して、インストールディレクトリとして/virtual/account/phpを指定

2.PATH設定
/php/binへのパスを設定する
$cd
$/bin/vi .bash_profile

export PATH=$PATH:~/php/bin

3.symfonyのインストール
pearによるsymfonyのインストール

$ pear channel-discover pear.symfony-project.com
$ pear install symfony/symfony
$ pear install http://phing.info/pear/phing-current.tgz

4.symfonyスクリプトの修正
symfonyスクリプトのphpのパスを変更

$ /bin/vi ~/php/bin/symfony
#!/usr/bin/env php → #!/usr/local/bin/php5

5.config/config.phpの修正
myproject/config/config.phpのsymfonyへのパスを修正

$sf_symfony_lib_dir  = '/virtual/account/php/lib/php/symfony';
$sf_symfony_data_dir = '/virtual/account/php/lib/php/data/symfony';

6.プロジェクトディレクトリをアップロード
FTPによりプロジェクトディレクトリをXREAサーバにアップロード
http://my.domain.com/myproject/
でアクセスする場合は
/virtual/account/public_html/my.domain.com/myproject

7.ログとキャッシュディレクトリのパーミッション変更
ユーザ権限とapache権限での書き込みを可能にするために、ログとキャッシュのパーミッションを変更
myproject/log → 777 or 707
myproject/log/myapp_dev.php → 666 or 606
myproject/cache/ → 777 or 707
myproject/cache/myapp → 777 or 707
myproject/cache/myapp/dev → 777 or 707
myproject/cache/myapp/prod → 777 or 707
myproject/cache/myapp/dev/config → 777 or 707
myproject/cache/myapp/prod/config → 777 or 707

< 追記 2007/06/04>
myproject/cache/myapp/dev/template → 777 or 707
myproject/cache/myapp/dev/template/my.domain/ → 777 or 707
myproject/cache/myapp/dev/template/my.domain/all/ → 777 or 707
myproject/cache/myapp/dev/template/my.domain/all/dirname/ → 777 or 707
myproject/cache/myapp/dev/template/my.domain/all/dirname/mymodule → 777 or 707
myproject/cache/myapp/dev/template/my.domain/all/dirname/sf_cache_partial → 777 or 707
myproject/cache/myapp/dev/template/my.domain/all/dirname/sf_cache_partial/mymodule → 777 or 707
myproject/cache/myapp/prod/template → 777 or 707
myproject/cache/myapp/prod/template/my.domain/ → 777 or 707
myproject/cache/myapp/prod/template/my.domain/all/ → 777 or 707
myproject/cache/myapp/prod/template/my.domain/all/dirname/ → 777 or 707
myproject/cache/myapp/prod/template/my.domain/all/dirname/mymodule → 777 or 707
myproject/cache/myapp/prod/template/my.domain/all/dirname/sf_cache_partial → 777 or 707
myproject/cache/myapp/prod/template/my.domain/all/dirname/sf_cache_partial/mymodule → 777 or 707

8.キャッシュの削除
ローカル環境でテストした際のキャッシュをサーバにアップロードしていると正常に動画しないので、キャッシュをクリア

$ symfony cc

http://my.domain.com/myproject/
あるいは
http://my.domain.com/myproject/myapp_dev.php/
にアクセスすれば、動作するはずです。