動画のストリーミング配信(修正版)

いろいろ調べた結果、前の記事の方法だとストリーミング配信されていなかった。


まずは再生用の動画を用意する。(sample.avi)

用意した動画をストリーミング配信用にエンコードします。
エンコード方法はWindow Mediaを利用してエンコードします。
新しいセッションに「ファイルの変換」を選択し、sample.aviをコピー元ファイルに指定します。
コンテンツの配信方法にWebサーバーを指定して、エンコードオプションと、各情報を入力してaviをwmvに変換します。


次にasxファイルを作成します。
sample.asx

<asx version="3.0">
<entry>
<title>サンプルストリーミング動画</title>
<author>黒い猫</author>
<copyright>Copyright (C) 2009 cats_mew. All Rights Reserved.</copyright>
<ref href="http://localhost:8080/Sample/sample.wmv" />
</entry>
</asx>

こんな感じで記述します。

entryタグを複数記述すると連続で表示されます。
titleタグは動画のタイトル
authorタグは作成者
copyrightタグは著作権
refタグのhref属性に動画ファイルを指定します。


HTMLは以下のように記述します。

<html>
<head>
<title>ストリーミング配信</title>
</head>
<body>

<object classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95" <!-- Widnow Media PlayerのID -->
        ID="mplayer" 
        width="400"    <!-- 表示幅 -->
        height="350">  <!-- 表示高さ -->

    <param name="src" value="./sample.asx">        <!-- asxファイル -->
    <param name="ShowStatusBar" value="true">      <!-- ステータスバーの表示 true or false -->
    <param name="AutoStart" value="true">          <!-- 自動再生 true or false -->
    <param name="enableContextMenu" value="false">
    <param name="stretchToFit" value="true">
    <param name="uiMode" value="full">
    <param name="Volume" value="80">               <!-- ボリューム 0〜100 -->

    <!-- Netscape用 -->
    <embed src="./sample.asx"            <!-- asxファイル -->
           type="application/x-mplayer2" 
           width="400"                   <!-- 表示幅 -->
           height="350"                  <!-- 表示高さ -->
           AnimationStart="0" 
           PlayCount="1" 
           ShowControls="1" 
           EnablePositionControls="1" 
           ShowPositionControls="1" 
           ShowAudioControls="1" 
           ShowTracker="1" 
           ShowStatusBar="1"              <!-- ステータスバーの表示 1 or 0 -->
           CanSeek="1" 
           AutoSize="0" 
           AllowScan="0" 
           AutoStart="1"                  <!-- 自動再生 1 or 0 -->
           ClickToPlay="0" 
           EnableContextmenu="0" 
           TransparentStart="0" 
           Volume="100"                   <!-- ボリューム 0〜100 -->
           pluginspage="http://www.microsoft.com/Windows/Downloads/Contents/Products/MediaPlayer/">
    </embed>

</object>

</body>
</html>

直接動画にアクセスするのではなく、asxファイルを経由して動画ファイルに接続します。
これでWindow Media Playerでストリーミング配信が可能になります。

Javaでオレオレ証明書

Axis2なんかでオレオレ証明書HTTPS接続する際にブラウザにセキュリティ証明書をインストールするだけだとダメだった。

どうやらJREオレオレ証明書を登録する必要がある。

  1. IEなどでオレオレ証明書をインストールする。
  2. IEなどから証明書をエクスポートする。
  3. JREに登録する。

以上の手順を踏む必要がる。


まずは「IEなどでオレオレ証明書をインストールする。」
これはセキュリティ警告の「証明書の表示」を押下し、証明書の「証明書のインストール」を押下してインストールします。


次に「IEなどから証明書をエクスポートする。」
これはインターネットオプションの「コンテンツ」タブの「証明書」を押下します。
すると「個人」、「ほかの人」などのタブの中に先ほどインストールした証明書があるはずです。
証明書を選択し、「エクスポート」を押下するとウィザードが表示されるので指示に従って証明書をエクスポートします。


最後に「JREに登録する。」
これはJRE標準のcacortsに証明書を登録する必要があります。
コマンドラインからkeytoolコマンドを使用して登録します。

keytool -import -trustcacerts -file (証明書のパス) -keystore (JREまでのパス)\lib\security\cacerts -storepass (パスワード)

パスワードはデフォルトは「changeit」です。


sample.cerという証明書をエクスポートしたとしてpleiadesJREに登録する場合は以下のようになります。

keytool -import -trustcacerts -file C:\sample.cer -keystore C:\pleiades\jre1.5\lib\security\cacerts -storepass changeit


「この証明書を信頼しますか?」と聞かれるので「yes」を入力して完了です。

動画のストリーミング配信

sample.aviを用意し、を記述すれば
Window Media Playerのプラグインを使用してsample.aviを再生します。

<html>
<head>
<title>ストリーミング配信</title>
</head>
<body>

<object classid="clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95" <!-- Widnow Media PlayerのID -->
        ID="mplayer" 
        width="400"    <!-- 表示幅 -->
        height="350">  <!-- 表示高さ -->

    <param name="src" value="./sample.avi">        <!-- 再生ファイル -->
    <param name="ShowStatusBar" value="true">      <!-- ステータスバーの表示 true or false -->
    <param name="AutoStart" value="true">          <!-- 自動再生 true or false -->
    <param name="enableContextMenu" value="false">
    <param name="stretchToFit" value="true">
    <param name="uiMode" value="full">
    <param name="Volume" value="80">               <!-- ボリューム 0〜100 -->

    <!-- Netscape用 -->
    <embed src="./sample.avi"            <!-- 再生ファイル -->
           type="application/x-mplayer2" 
           width="400"                   <!-- 表示幅 -->
           height="350"                  <!-- 表示高さ -->
           AnimationStart="0" 
           PlayCount="1" 
           ShowControls="1" 
           EnablePositionControls="1" 
           ShowPositionControls="1" 
           ShowAudioControls="1" 
           ShowTracker="1" 
           ShowStatusBar="1"              <!-- ステータスバーの表示 1 or 0 -->
           CanSeek="1" 
           AutoSize="0" 
           AllowScan="0" 
           AutoStart="1"                  <!-- 自動再生 1 or 0 -->
           ClickToPlay="0" 
           EnableContextmenu="0" 
           TransparentStart="0" 
           Volume="100"                   <!-- ボリューム 0〜100 -->
           pluginspage="http://www.microsoft.com/Windows/Downloads/Contents/Products/MediaPlayer/">
    </embed>

</object>

</body>
</html>

Ajaxを利用してPostGISの情報をGoogle Mapsに表示する。

まずはHTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="Content-Script-Type" content="text/javascript">
    <meta http-equiv="Content-Style-Type" content="text/css">
    <title>地図サンプル</title>
    <script type="text/javascript" src="js/prototype.js"></script>
    <script type="text/javascript" charset="utf-8" src="http://maps.google.com/maps?file=api&v=2&key=AB・・・&hl=ja"></script>
    <script>
    <!--
    var map;
    var objArray = new Array();
    function initOnLoad() {
        map = new GMap2($("MAP"));
        map.addControl(new GLargeMapControl());
        map.addControl(new GMapTypeControl());
        map.enableContinuousZoom();
        map.enableScrollWheelZoom();
        map.disableDoubleClickZoom();
        map.addMapType(G_PHYSICAL_MAP);
        map.addMapType(G_SATELLITE_3D_MAP);
        map.setCenter(new GLatLng(35.689487380721324, 139.6917736530304), 17);

        GEvent.addListener(map, "moveend", ajaxRequest);
    }
    function ajaxRequest() {
        var request = GXmlHttp.create();
        var url = "http://localhost:8080/Sample/map";
        var bounds = map.getBounds();
        var ne = bounds.getNorthEast();
        var sw = bounds.getSouthWest();
        var params = "n=" + ne.lat() + "&s=" + sw.lat() + "&e=" + ne.lng() + "&w=" + sw.lng();
        request.open("POST", url, true);
        request.onreadystatechange = function() {
            if( request.readyState == 4 ) {
                for( var i = 0; i < objArray.length; i++ ) {
                    map.removeOverlay(objArray[i]);
                }
                objArray = new Array();
                var xml = request.responseXML;
                var features = xml.documentElement.getElementsByTagName("point");
                for( var i = 0; features && i < features.length; i++ ) {
                    var feature = features[i];
                    var latlng = feature.getElementsByTagName("latlng")[0].firstChild.nodeValue;
                    var obj = new GMarker(stringToGLatLngArray(latlng)[0]);
                    map.addOverlay(obj);
                    objArray.push(obj);
                }
                features = xml.documentElement.getElementsByTagName("linestring");
                for( var i = 0; features && i < features.length; i++ ) {
                    var feature = features[i];
                    var latlng = feature.getElementsByTagName("latlng")[0].firstChild.nodeValue;
                    var obj = new GPolyline(stringToGLatLngArray(latlng), "#FF0000", 5);
                    map.addOverlay(obj);
                    objArray.push(obj);
                }
                features = xml.documentElement.getElementsByTagName("polygon");
                for( var i = 0; features && i < features.length; i++ ) {
                    var feature = features[i];
                    var latlng = feature.getElementsByTagName("latlng")[0].firstChild.nodeValue;
                    var obj = new GPolygon(stringToGLatLngArray(latlng), "#00FF00", 5, 1, "#00FF00", 0.2);
                    map.addOverlay(obj);
                    objArray.push(obj);
                }
            }
        }
        request.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");
        request.send(params);
    }
    function stringToGLatLngArray(str) {
        var geometries = str.split(",");
        var geomArray = new Array();
        for( var i = 0; i < geometries.length; i++ ) {
            var geometry = geometries[i].split(" ");
            geomArray.push(new GLatLng(geometry[1], geometry[0]));
        }
        return geomArray;
    }
    // -->
    </script>
</head>
<body onload="initOnLoad();">
    <div id="MAP" style="width: 100%; height: 500px;">&nbsp;</div>
</body>
</html>


DBはPostGISを利用可能な状態にして

sample=# CREATE TABLE GeometryTable ( id INTEGER NOT NULL );
sample=# SELECT AddGeometryColumn('geometrytable', 'geometry', 4326, 'GEOMETRY', 2);
sample=#
sample=# \d GeometryTable
 カラム    |  型       |  修飾語
----------------------------------
 id        | integer   | not null
 geometry  | geometry  |
CHECK 制約:
    "enforce_dims_geometry" CHECK (ndims(geometry) = 2)
    "enforce_srid_geometry" CHECK (srid(geometry) = 4326)
sample=#
sample=# INSERT INTO GeometryTable VALUES ( 1, GeomFromText('POINT(139.6917736530304 35.689487380721324)', 4326));
sample=# INSERT INTO GeometryTable VALUES ( 2, GeomFromText('LINESTRING(139.6921142935753 35.69046768390191,139.69293236732483 35.68719995978114)', 4326));
sample=# INSERT INTO GeometryTable VALUES ( 3, GeomFromText('POLYGON((139.690692722797 35.6902389475707,139.691510796547 35.6869494287404,139.694270789623 35.687415633699,139.69346344471 35.690718203893,139.69069272279735.6902389475707))', 4326));


生成されるXMLはこんな感じ

<?xml version="1.0" encoding="UTF-8" ?>
<features>
    <point>
    <latlng>139.6917736530304 35.689487380721324</latlng>
    </point>
    <linestring>
        <latlng>139.6921142935753 35.69046768390191,139.69293236732483 35.68719995978114</latlng>
    </linestring>
    <polygon>
        <latlng>139.6906954050064 35.69023894757071,139.69150006771088 35.68694942874041,139.69426542520523 35.68741345517749,139.69345808029175 35.690720382324216,139.6906954050064 35.69023894757071</latlng>
    </polygon>
</features>


XMLを生成するServlet

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 北
    String north = request.getParameter("n");
    // 西
    String west = request.getParameter("w");
    // 東
    String east = request.getParameter("e");
    // 南
    String south = request.getParameter("s");

    StringBuffer geometry = new StringBuffer("POLYGON((");
    geometry.append(west).append(" ").append(north).append(",");
    geometry.append(west).append(" ").append(south).append(",");
    geometry.append(east).append(" ").append(south).append(",");
    geometry.append(east).append(" ").append(north).append(",");
    geometry.append(west).append(" ").append(north);
    geometry.append("))");

    String sql = "SELECT AsText(geometry) AS geometry FROM GeometryTable WHERE ST_Intersects(geometry, GeomFromText(?, 4326)) = True";

    Connection con = null;
    Statement st = null;
    ResultSet rs = null;
    try {
        Class.forName("org.postgresql.Driver");
        con = DriverManager.getConnection("jdbc:postgresql:sample", "postgres", "postgres");
        st = con.createStatement(sql);
        st.setString(1, geometry.toString());
        rs = st.executeQuery();

        StringBuffer result = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
        result.append("<features>");
        while( rs.next() ) {
            String geometry = rs.getString("geometry");
            if( geometry.startsWith("POINT") ) {
                result.append("<point><latlng>").append(geometry.substring(6, geometry.length() - 1)).append("</latlng></point>");
            } else if( geometry.startsWith("LINESTRING") ) {
                result.append("<linestring><latlng>").append(geometry.substring(11, geometry.length() - 1)).append("</latlng></linestring>");
            } else if( geometry.startsWith("POLYGON") ) {
                result.append("<polygon><latlng>").append(geometry.substring(9, geometry.length() - 2)).append("</latlng></polygon>");
            }
        }
        result.append("</features>");
    } catch( Exception e ) {
        return;
    } finally {
        if( rs != null ) {
            try {
                rs.close();
            } catch( SQLException e ) {
            }
        }
        if( st != null ) {
            try {
                st.close();
            } catch( SQLException e ) {
            }
        }
        if( con != null ) {
            try {
                con.close();
            } catch( SQLException e ) {
            }
        }
    }
    response.setContentType("text/xml; charset=utf-8");
    response.getWriter().println(result);
}


この状態で東京都庁周辺を表示する、しないによってサーバから取得するデータ(XML)が動的に変わります。

CentOS5.3にPostGISをインストールする。

PostgreSQLがインストールされていることが前提です。
インストール手順は前回の記事を参照


GCCなどのコンパイラが無い場合はyumでインストールします。

yum search gcc-c++
yum install gcc-c++


まずはPROJをインストールします。

PROJをダウンロードし、解凍します。

wget http://download.osgeo.org/proj/proj-4.6.1.tar.gz
tar xvfz proj-4.6.1.tar.gz


解凍したproj-4.6.1のコンパイルとインストールです。

cd /root/proj-4.6.1
./configure
make
make install


次にGEOSをインストールします。

GEOSをダウンロードして解凍します。

wget http://download.osgeo.org/geos/geos-3.1.1.tar.bz2
tar -jxvf geos-3.1.1.tar.bz2


解凍したgeos-3.1.1のコンパイルとインストールです。

cd /root/geos-3.1.1
./configure
make
make install

やっとメインのPostGISをインストールします。

先にPostgreSQLを停止します。

service postgresql stop


PostGISをダウンロードして解凍します。

wget http://www.postgis.org/download/postgis-1.4.0.tar.gz
tar xvfz postgis-1.4.0.tar.gz


解凍したpostgis-1.4.0のコンパイルとインストールです。

cd /root/postgis-1.4.0
./configure
make
make install

次に設定です。
PROJとGEOSのライブラリを /etc/ld.so.conf に登録します。

/etc/ld.so.conf

include ld.so.fonf.d/*.conf
/usr/local/lib


登録したライブラリを有効にします。

ldconfig

最後にデータベースの作成方法です。

PostgreSQLのサービスを開始します

service postgresql start


とりあえず以下のようなデータベースを作成します。

createdb -EUTF-8 -Upostgres template_postgis


上で作成したデータベースにPL/pgSQLを有効にし、PostGISの関数等を組み込みます。

createlang plpgsql template_postgis
psql -Upostgres -f /usr/share/pgsql/contrib/postgis.sql template_postgis
psql -Upostgres -f /usr/share/pgsql/contrib/spatial_ref_sys.sql template_postgis


これでPostGISの利用が可能となりました。

毎回 PL/pgSQLpostgis.sql 、 spatial_ref_sys.sql を取り込むのはめんどくさいので、PostGISを利用するデータベースには上記で作成した template_postgis を読み込むようにします。

createdb -EUTF-8 -Upostgres -Ttemplate_postgis Sample


操作については以前の記事等を参考にしてください

PostgreSQL8.3をCentOS5.3にインストール

まずインストール済みのPostgreSQLがあればアンインストールします。

インストール済みのPostgreSQLのパッケージを検索します。

yum list installed | grep postgresql


以下のような結果が返ってきたらインストールされています。

postgresql-libs.i386        8.1.11-1.el5_1.1      base


アンインストールするには

yum remove postgresql-libs


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



次に必要なバージョンのRPMを取得します。
8.3をインストールするためにここからRPMを取得します。
RPMのダウンロードが完了したら展開します。

wget http://yum.pgsqlrpms.org/reporpms/8.3/pgdg-centos-8.3-6.noarch.rpm

rpm -ivh pgdg-centos-8.3-6.noarch.rpm


正常に完了すると /etc/yum.repos.d/pgdg-83-centos.repo が追加されます。


/etc/yum.repos.d/CentOS-Base.repo の[base]、[updates]の最後にそれぞれ exclude=postgres* を追加します。

[base]
name=CentOS-$releaserver - Base
・
・
exclude=postgres*

[updates]
name=CentOS-$releaserver - Updates
・
・
exclude=postgres*

[addons]
・
・


ここまで終わったらyumでさっき追加したリポジトリを使用してインストールします。

yum install postgresql
yum install postgresql-server
yum install postgresql-contrib
yum install postgresql-devel


インストールが完了したらデータベースを初期化します。

service postgresql initdb
または
initdb --encoding=UTF8 --no-locale


/var/lib/pgsql/pgstartup.log を確認してエラーが発生していないことを確認します。


起動

/etc/rc.d/init.d/postgresql start
または
service postgresql start


postgresユーザのパスワードを設定します。(CentOSのパスワード)

passwd postgres
New UNIX password:
Retype New UNIX password:


postgresユーザのPostgreSQLでのパスワードを設定します。

su - postgres
psql -Upostgres postgres
ALTER USER postgres WITH PASSWORD 'postgres';
\q
exit


このあとは通常のユーザ(rootやその他のユーザ)でpsqlコマンドを使用してPostgreSQLを利用できます。
ALTER USERで設定したパスワードを使用します。

psql -Upostgres postgres
Password for user postgres: postgres


/var/lib/pgsql/data/pg_hba.confの設定を変更します。

# "local" is for UNIX domain socket connections only
#local    all    all        ident sameuser
local    all    all        md5

# IPv4 local connections
#local    all    all    127.0.0.0/32    ident sameuser
local    all    all    127.0.0.0/32    md5

# IPv6 local connections
#local    all    all    ::1/128    ident sameuser
local    all    all    ::1/128    md5


再起動します。

service postgresql restart

IEで親ウィンドウに要素を追加する。

IEで親ウィンドウに要素を作成して追加する際に子ウィンドウのdocumentを使用するとうまくいかない。


親ウィンドウ

<table id="table">
    <thead>
        <tr><th>label</th></tr>
    </thead>
    <tbody>
    </tbody>
</table>


子ウィンドウJavaScript

function test() {
    var opener = window.opener;
    var tbody = opener.getElementById("table").getElementsByTagName("tbody");
    var tr = document.createElement("tr");
    var td = document.createElement("td");
    td.innerText = "test"
    tr.appnedChild(td);
    tbody.appendChild(tr);
}


この状態で実行してもtbody.appendChild(tr);でエラーが発生します。
これを回避するには

function test() {
    var opener = window.opener;
    var doc = opener.document;
    var tbody = opener.getElementById("table").getElementsByTagName("tbody");
    var tr = doc.createElement("tr");
    var td = doc.createElement("td");
    td.innerText = "test"
    tr.appnedChild(td);
    tbody.appendChild(tr);
}

このように親ウィンドウのdocumentを使用してあげればうまくいきます。