2014年4月18日金曜日

Red5用のプロジェクト作成

前回の「Red5用のEclipse Plugin導入」で、
Eclipseのプラグインがインストールできたので、次はRed5用のプロジェクトを作成します(`・ω・´)シャキーン

Eclipseを起動したら、New > Java Project を選択する。



プロジェクト名に、「oflaDemo2」を入力して、「次へ」を押します。



Javaの設定画面が表示されるので、そのまま「Finish」を押します。



プロジェクトの作成が完了したら、
oflaDemo2を右クリックして、New > Folder を選択する



Folder nameに「WEB-INF/classes」を入力して、「Finish」を押す



もう一度New > Folder を選択して、
Foloder nameに「WEB-INF/src」を入力して、「Finish」を押す



作成が完了したら、デフォルトで作成された「src」フォルダのリンクをはずします。

oflaDemo2の配下にあるsrcを右クリックして、
Build Path > Remove from Build Pathを押します。


除外された状態



除外したsrcを選択して、deleteを押して削除してしまいます。




削除後のディレクトリ構成はこんな感じです。



Java のビルドパス設定のソース・フォルダーとライブラリーの設定を行います。
 oflaDemo2 プロジェクトを右クリックして、 Properties を押します。



プロパティ画面で、Java Build Path を選択して
右側にある Source タブを選択し、 Add Folder を押します。



ソースフォルダー選択画面が表示されたら、
WEB-INF 配下にある src をチェックして、「OK」を押します。


ビルドパス設定画面に戻ったら、
Browse... を選択します



選択画面が表示されたら、
WEB-INF 配下にある classes を選択して、「OK」を押します



ビルドパス設定画面に戻ったら、外部JARの追加を行います。

Librariesタブを選択して、Add External JARs... を押します。



JARの選択画面が開いたら、 red5.jar を選択します。
※red5.jarはwindows版のred5をインストールすると、インストール先のディレクトリにあります。

C:\Program Files (x86)\Red5\red5.jar


画面が戻ると追加されています。


今度はライブラリー関係を追加します。

再度、Add External JARs... を押します。

JARの選択画面が開いたら、 Windows版Red5のインストール先のlibディレクトリの中にあるjarを全て選択します。

C:\Program Files (x86)\Red5\lib


ビルドパス画面に戻ったら「OK」を押します。



現在のディレクトリ構成はこんな感じになります。



red5 のdemoで利用していたソースを利用するため、
demoのソースコードをプロジェクトに配置します。

今回は oflaDemo のデモを配置します。
※事前にWindows版のred5とデモをインストールしている必要があります。

C:\Program Files (x86)\Red5\webapps\oflaDemo\WEB-INFの
「web.xml」「red5-web.xml」「red5-web.properties」を
oflaDemo2プロジェクトのWEB-INF配下にファイルをドラッグコピーします。



コピーされると次のようになります。





次に、workspaceに作成されているディレクトリを開いて、ファイルを作成していきます。

今回は、C:\workspace\red5\testの位置にワークスペースを作り、
プロジェクトを作って作業をしていますので、
プロジェクトのベースのパスは「C:\workspace\red5\test\oflaDemo2」になっています。

プロジェクト直下のディレクトリに、WEB-INFディレクトリがあるので、
その中のclassesを開きます。

その中に、「applications」という名前でディレクトリを作ります。



作成したディレクトリの中に、Red5をインストールディレクトリにある、
oflaDemoサンプルのclassesに配置されている次のファイルを先ほど作成した
C:\workspace\red5\test\oflaDemo2\WEB-INF\classes\applicationsにコピーします。

・demoservice.js
・demoservice.py
・demoservice.rb
・logback-oflaDemo.xml
・main.groovy
・main.js
・main.py
・main.rb





次に、C:\workspace\red5\test\oflaDemo2\WEB-INF\classesに
「org」というディレクトリを作成します。



さらにorgのディレクトリの中にred5/demos/oflaDemo2というディレクトリを作っていきます。
最後に作られたoflaDemo2のディレクトリを開いて、
その中に次のファイルを配置します。

・Application.java
・DemoService.java
・DemoServiceImpl.java
・IDemoService.java
・SecurityTest.java

ファイルはこちらからダウンロードしてください。
http://red5.googlecode.com/svn/java/example/trunk/oflaDemo/src/main/java/org/red5/demos/oflaDemo/

svnをチェックアウトしておくと良いかも!

リポジトリURL
http://red5.googlecode.com/svn/

ダウンロードしたファイルを
C:\workspace\red5\test\oflaDemo2\WEB-INF\classes\org\red5\demos\oflaDemo2の中に配置する


配置した各ファイルをEclipseにドラッグさせて認識させてます。
C:\workspace\red5\test\oflaDemo2\WEB-INF\classes配下にある「org」と「applications」の2つのディレクトリをEclipse上のWEB-INF/srcにドラッグします。

ドラッグしてコピーし終わったら、プルじぇくとめいのoflaDemo2をクリックしてF5を押して、
プロジェクトをリフレッシュさせます。

コピーされたファイルが正しく認識されると、
javaのエラーマークが表示されます。
※基にしたサンプルデモとは別名のパッケージ名を設定してためエラーになっています。


今度は、このエラーを修正していきます。

基本的には、元にしたサンプルデモで利用していたパッケージ名が
org.red5.demos.oflaDemoだったものをorg.red5.demos.oflaDemo2に変更した影響で発生しているエラーのため、ソースコードに書かれている、「oflaDemo」という記述を
「oflaDemo2」に変更するだけになります。

各ファイルの役割について
・web.xml
アプリケーションの動作を規定する設定ファイルとなります。

・red5-web.xml
Red5 アプリケーションを構成しているファイルとなります。
スクリプト実装または Java アプリケーションは、Spring bean 要素で構成されます。

・red5-web.properties
Red5 アプリケーションのパスやホスト名、あるいはIPアドレスを構成しているファイルとなります。

・demoservice.js
動画再生用のクラスとなっています。
ファイルはjavascriptで構成されています。

・demoservice.py
動画再生用のクラスとなっています。
ファイルはPythonで構成されています。

・demoservice.rb
動画再生用のクラスとなっています。
ファイルはJRubyで構成されています。

・main.groovy、main.js、main.py、main.rb
red5アプリケーションを動作する際の基本的ファイル。基本的に変更しない。
ファイル構成については、groovy・javascript・Python・Rubyの4つの言語で構成

・Application.java
ライブストリーミングなどをする際に、中心となるアプリケーションファイルとなります。
ストリーミングをする際に、中継地点的な役割を担っています。

・DemoService.java
動画配信などをする際に、中心となるアプリケーションファイル

・DemoServiceImpl.java
ログ出力用のクラス

・IDemoService.java
インターフェイス

・SecurityTest.java
ストリーミングサービスを提供した際に、ファイルやフォルダが存在の有無などを確認するクラス


各ソースの変更後のソースが次のようになります。

・Application.java
package org.red5.demos.oflaDemo2;

import java.util.*;
import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IConnection;
import org.red5.server.api.scope.IScope;
import org.red5.server.api.stream.IServerStream;

public class Application extends ApplicationAdapter {

 private IScope appScope;

 private IServerStream serverStream;
 
 /** {@inheritDoc} */
    @Override
 public boolean appStart(IScope app) {
     super.appStart(app);
  log.info("oflaDemo2 appStart");
  System.out.println("oflaDemo2 appStart");     
  appScope = app;
  return true;
 }

 /** {@inheritDoc} */
    @Override
 public boolean appConnect(IConnection conn, Object[] params) {
  log.info("oflaDemo2 appConnect");
  IScope appScope = conn.getScope();
  log.debug("App connect called for scope: {}", appScope.getName());
  // getting client parameters
  Map<String, Object> properties = conn.getConnectParams();
  if (log.isDebugEnabled()) {
   for (Map.Entry<String, Object> e : properties.entrySet()) {
    log.debug("Connection property: {} = {}", e.getKey(), e.getValue());
   }
  }
  
  // Trigger calling of "onBWDone", required for some FLV players 
  // commenting out the bandwidth code as it is replaced by the mina filters
  //measureBandwidth(conn);
//  if (conn instanceof IStreamCapableConnection) {
//   IStreamCapableConnection streamConn = (IStreamCapableConnection) conn;
//   SimpleConnectionBWConfig bwConfig = new SimpleConnectionBWConfig();
//   bwConfig.getChannelBandwidth()[IBandwidthConfigure.OVERALL_CHANNEL] =
//    1024 * 1024;
//   bwConfig.getChannelInitialBurst()[IBandwidthConfigure.OVERALL_CHANNEL] =
//    128 * 1024;
//   streamConn.setBandwidthConfigure(bwConfig);
//  }
  
//  if (appScope == conn.getScope()) {
//   serverStream = StreamUtils.createServerStream(appScope, "live0");
//   SimplePlayItem item = new SimplePlayItem();
//   item.setStart(0);
//   item.setLength(10000);
//   item.setName("on2_flash8_w_audio");
//   serverStream.addItem(item);
//   item = new SimplePlayItem();
//   item.setStart(20000);
//   item.setLength(10000);
//   item.setName("on2_flash8_w_audio");
//   serverStream.addItem(item);
//   serverStream.start();
//   try {
//    serverStream.saveAs("aaa", false);
//    serverStream.saveAs("bbb", false);
//   } catch (Exception e) {}
//  }
   
  return super.appConnect(conn, params);
 }

 /** {@inheritDoc} */
    @Override
 public void appDisconnect(IConnection conn) {
  log.info("oflaDemo2 appDisconnect");
  if (appScope == conn.getScope() && serverStream != null) {
   serverStream.close();
  }
  super.appDisconnect(conn);
 }
}

・DemoService
package org.red5.demos.oflaDemo2;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.red5.logging.Red5LoggerFactory;
import org.red5.server.api.Red5;
import org.red5.server.api.scope.IScope;
import org.slf4j.Logger;
import org.springframework.core.io.Resource;

public class DemoService {

 private static Logger log = Red5LoggerFactory.getLogger(DemoService.class, "oflaDemo2");
 
 {
  log.info("oflaDemo2 DemoService created");
 }
 
 private String formatDate(Date date) {
  SimpleDateFormat formatter;
  String pattern = "dd/MM/yy H:mm:ss";
  Locale locale = new Locale("en", "US");
  formatter = new SimpleDateFormat(pattern, locale);
  return formatter.format(date);
 }

 /**
  * Getter for property 'listOfAvailableFLVs'.
  *
  * @return Value for property 'listOfAvailableFLVs'.
  */
 public Map<String, Map<String, Object>> getListOfAvailableFLVs() {
  IScope scope = Red5.getConnectionLocal().getScope();
  Map<String, Map<String, Object>> filesMap = new HashMap<String, Map<String, Object>>();
  try {
   log.debug("Getting the media files");
   addToMap(filesMap, scope.getResources("streams/*.flv"));
   addToMap(filesMap, scope.getResources("streams/*.f4v"));
   addToMap(filesMap, scope.getResources("streams/*.mp3"));
   addToMap(filesMap, scope.getResources("streams/*.mp4"));
   addToMap(filesMap, scope.getResources("streams/*.m4a"));
   addToMap(filesMap, scope.getResources("streams/*.3g2"));   
   addToMap(filesMap, scope.getResources("streams/*.3gp"));   
  } catch (IOException e) {
   log.error("", e);
  }
  return filesMap;
 }

 private void addToMap(Map<String, Map<String, Object>> filesMap, Resource[] files)
   throws IOException {
  if (files != null) {
   for (Resource flv : files) {
    File file = flv.getFile();
    Date lastModifiedDate = new Date(file.lastModified());
    String lastModified = formatDate(lastModifiedDate);
    String flvName = flv.getFile().getName();
    String flvBytes = Long.toString(file.length());
    if (log.isDebugEnabled()) {
     log.debug("flvName: {}", flvName);
     log.debug("lastModified date: {}", lastModified);
     log.debug("flvBytes: {}", flvBytes);
     log.debug("-------");
    }
    Map<String, Object> fileInfo = new HashMap<String, Object>();
    fileInfo.put("name", flvName);
    fileInfo.put("lastModified", lastModified);
    fileInfo.put("size", flvBytes);
    filesMap.put(flvName, fileInfo);
   }
  }
 }

}

・DemoServiceImpl
package org.red5.demos.oflaDemo2;

import java.util.HashMap;
import java.util.Map;

import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;

public class DemoServiceImpl implements IDemoService {
 
 private static Logger log = Red5LoggerFactory.getLogger(DemoServiceImpl.class, "oflaDemo2");
 
 /**
     * Getter for property 'listOfAvailableFLVs'.
     *
     * @return Value for property 'listOfAvailableFLVs'.
     */
    public Map<String, Map<String, Object>> getListOfAvailableFLVs() {
     log.debug("getListOfAvailableFLVs empty");
  return new HashMap<String, Map<String, Object>>(1);
 }

    public Map<String, Map<String, Object>> getListOfAvailableFLVs(String string) {
     log.debug("getListOfAvailableFLVs, Got a string: {}", string);
     return getListOfAvailableFLVs();
    }

}
・IDemoService
package org.red5.demos.oflaDemo2;

import java.util.Map;

public interface IDemoService {

 /**
     * Getter for property 'listOfAvailableFLVs'.
     *
     * @return Value for property 'listOfAvailableFLVs'.
     */
    public Map<String, Map<String, Object>> getListOfAvailableFLVs();

    public Map<String, Map<String, Object>> getListOfAvailableFLVs(String string);

}
・SecurityTest
package org.red5.demos.oflaDemo2;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class SecurityTest
 */
public class SecurityTest extends HttpServlet {

 private static final long serialVersionUID = 17227839L;

 /**
  * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse
  *      response)
  */
 protected void service(HttpServletRequest request,
   HttpServletResponse response) throws ServletException, IOException {

  PrintWriter out = response.getWriter();
  
  try {
   File rootDir = new File("/");
   out.print("\nPath: " + rootDir.getAbsolutePath());
   if (rootDir.exists()) {
    out.print("\nRoot '/' exists");
    if (rootDir.canRead()) {
     out.print("\nCan read from Root");
     if (rootDir.canWrite()) {
      out.print("\nCan write to Root");
     }
    }
   }
  } catch (Exception e) {
   out.print("\nException with Root: " + e.getMessage());
  }

  try {
   File cDir = new File("file://C:/");
   out.print("\nPath: " + cDir.getAbsolutePath());   
   if (cDir.exists()) {
    out.print("\nC drive exists");
    if (cDir.canRead()) {
     out.print("\nCan read from C drive");
     if (cDir.canWrite()) {
      out.print("\nCan write to C drive");
     }
    }
   }
  } catch (Exception e) {
   out.print("\nException with C drive: " + e.getMessage());
  }

  try {
   File servDir = new File(getServletContext().getRealPath("/"));
   out.print("\nPath: " + servDir.getAbsolutePath());
   if (servDir.exists()) {
    out.print("\nServlet directory exists");
    if (servDir.canRead()) {
     out.print("\nCan read from Servlet directory");
     if (servDir.canWrite()) {
      out.print("\nCan write to Servlet directory");
     }
    }
   }
  } catch (Exception e) {
   out.print("\nException with servlet directory: " + e.getMessage());
  }
  
 }

}

・demoservice.js
/*
 * demoservice.js - a translation into JavaScript of the ofla demo DemoService class, a Red5 example.
 *
 * @see http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference
 * @author Paul Gregoire
 */

importPackage(Packages.org.red5.server.api);
importPackage(Packages.org.springframework.core.io);
importPackage(Packages.org.apache.commons.logging);

importClass(java.io.File);
importClass(java.util.HashMap);
importClass(java.text.SimpleDateFormat);
importClass(Packages.org.springframework.core.io.Resource);
importClass(Packages.org.red5.server.api.Red5);

function DemoService() {
 this.className = 'DemoService';
 log.debug('DemoService init');

    if (supa) {
        DemoService.prototype = supa;
    }

 getListOfAvailableFLVs = function() {
  log.debug('getListOfAvailableFLVs');
  log.debug('Con local: ' + Red5.getConnectionLocal());
  var scope = Red5.getConnectionLocal().getScope();
  log.debug('Scope: ' + scope);
  var filesMap = new HashMap(3);
  var fileInfo;
  try {
   print('Getting the FLV files');
   //var flvs = scope.getResources("streams/*.flv"); //Resource[]
   var serverRoot = java.lang.System.getProperty('red5.root');
   log.debug('Red5 root: ' + serverRoot);
   var streamsDir = new File(serverRoot + '/webapps/oflaDemo2/streams/');
   var flvs = streamsDir.listFiles();
   log.debug('Flvs: ' + flvs);
   log.debug('Number of flvs: ' + flvs.length);
   for (var i=0;i<flvs.length;i++) {
    var file = flvs[i];
    log.debug('file: ' + file);
    log.debug('java.io.File type: ' + (file == typeof(java.io.File)));
    log.debug('js type: ' + typeof(file));
    log.debug('file path: ' + file.path);
    log.debug('file url: ' + file.URL);
    //var fso = new File(serverRoot + '/webapps/oflaDemo2' + file.path);
    var fso = file;
    var flvName = fso.getName();
    if (flvName.indexOf('.flv') < 1) {
        continue;
    }
    log.debug('flvName: ' + flvName);
    log.debug('exist: ' + fso.exists());
    log.debug('readable: ' + fso.canRead());
    //loop thru props
    var flvBytes = 0;
    if ('length' in fso) {
     flvBytes = fso.length();
    } else {
     log.warn('Length not found');
    }
    log.debug('flvBytes: ' + flvBytes);
    var lastMod = '0';
    if ('lastModified' in fso) {
     lastMod = this.formatDate(new java.util.Date(fso.lastModified()));
    } else {
     log.debug('Last modified not found');
    }

    print('FLV Name: ' + flvName);
    print('Last modified date: ' + lastMod);
    print('Size: ' + flvBytes);
    print('-------');

    fileInfo = new HashMap(3);
    fileInfo.put("name", flvName);
    fileInfo.put("lastModified", lastMod);
    fileInfo.put("size", flvBytes);
    filesMap.put(flvName, fileInfo);
   }
  } catch (e) {
   log.warn('Error in getListOfAvailableFLVs: ' + e);
  }
  return filesMap;
 };

    formatDate = function(date) {
     //java 'thread-safe' date formatting
     return new SimpleDateFormat("dd/MM/yyyy hh:mm:ss").format(date);
    };

    toString = function(string) {
     return 'Javascript:DemoService';
    };

    doesNotUnderstand = function(name) {
        print("Unknown method called: " + name + "\n");
        for (n in context){
            print('Context: '+n);
        }
        if (name in this.__proto__) {
            if (arguments.length > 0) {
                return this.__proto__[name](arguments);
            } else {
                return this.__proto__[name]();
            }
        }
    };

}

DemoService.__has__ = function(name) {
    println('Has: '+name);
    return true;
};

DemoService.__get__ = function(name) {
    println('Get: '+name);
    if (name in this) {
        return this[name];
    } else if (typeof(this['doesNotUnderstand']) == 'function') {
        return function() {
            return this.doesNotUnderstand(name, arguments);
        }
    } else {
        return undefined;
    }
};

DemoService();
・demoservice.py
"""
demoservice.py - a translation into Python of the ofla demo application, a Red5 example.

@author The Red5 Project (red5@osflash.org)
@author Joachim Bauch (jojo@struktur.de)
"""

from java.io import File
from java.lang import System
from java.text import SimpleDateFormat
from java.util import Date
from java.util import HashMap

from org.red5.server.api import Red5
from org.red5.demos.oflaDemo2 import IDemoService

class DemoService(IDemoService):
    
    def getListOfAvailableFLVs(self):
        """Return list of .flv files that can be streamed."""
        scope = Red5.getConnectionLocal().getScope()
        serverRoot = System.getProperty('red5.root')
        filesMap = HashMap()
        try:
            print 'Getting the FLV files'
            flvs = scope.getResources("streams/*.flv")
            for file in flvs:
                fso = File(serverRoot + '/webapps/oflaDemo2' + file.path)
                flvName = fso.getName()
                flvBytes = 0
                if hasattr(fso, 'length'):
                    flvBytes = fso.length()
                else:
                    print 'Length not found'
                
                lastMod = '0'
                if hasattr(fso, 'lastModified'):
                    lastMod = self.formatDate(Date(fso.lastModified()))
                else:
                    log.debug('Last modified not found')

                print 'FLV Name:', flvName
                print 'Last modified date:', lastMod
                print 'Size:', flvBytes
                print '-------'
                
                fileInfo = HashMap(3);
                fileInfo["name"] = flvName
                fileInfo["lastModified"] = lastMod
                fileInfo["size"] = flvBytes
                filesMap[flvName] = fileInfo
        except Exception, e:
            print 'Error in getListOfAvailableFLVs:', e
        
        return filesMap;

    def formatDate(self, date):
        return SimpleDateFormat("dd/MM/yyyy hh:mm:ss").format(date)

def getInstance(*args):
    print 'Arguments:', args
    return DemoService()

・demoservice.rb
# JRuby - style
require 'java'
module RedFive
    include_package "org.springframework.core.io"
    include_package "org.red5.server.webapp.oflaDemo2"
end
include_class "org.red5.server.api.Red5"
include_class "java.util.HashMap"

#
# demoservice.rb - a translation into Ruby of the ofla demo application, a red5 example.
#
# @author Paul Gregoire
#
class DemoService < RedFive::DemoServiceImpl

    attr_reader :filesMap
    attr_writer :filesMap

 def initialize
    puts "Initializing ruby demoservice"
    super
    @filesMap = HashMap.new
 end

 def getListOfAvailableFLVs
  puts "Getting the FLV files"
  begin
#      puts "R5 con local: #{Red5::getConnectionLocal}"
#      puts "Scope: #{Red5::getConnectionLocal.getScope}"
#      puts "Root path: #{File.expand_path('/')}"
#      puts "Current path:  #{File.expand_path('webapps/oflaDemo2/')}"
            dirname = File.expand_path('webapps/oflaDemo2/streams').to_s
   Dir.open(dirname).entries.grep(/\.flv$/) do |dir|
       dir.each do |flvName|
             fileInfo = HashMap.new
             stats = File.stat(dirname+'/'+flvName)
             fileInfo["name"] = flvName
             fileInfo["lastModified"] = stats.mtime
             fileInfo["size"] = stats.size || 0
                    @filesMap[flvName] = fileInfo
                    print 'FLV Name:', flvName
                    print 'Last modified date:', stats.mtime
                    print 'Size:', stats.size || 0
                    print '-------'
                end
            end
  rescue Exception => ex
   puts "Error in getListOfAvailableFLVs #{errorType} \n"
   puts "Exception: #{ex} \n"
   puts caller.join("\n");
  end
  return filesMap
 end

 def formatDate(date)
  return date.strftime("%d/%m/%Y %I:%M:%S")
 end

    def method_missing(m, *args)
      super unless @value.respond_to?(m)
      return @value.send(m, *args)
    end

end
・logback-oflaDemo.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

 <contextName>oflaDemo2</contextName>
 
 <jmxConfigurator contextName="oflaDemo2" />

 <appender name="OFLA" class="ch.qos.logback.core.FileAppender">
  <File>log/oflademo2.log</File>
  <Append>false</Append>
  <Encoding>UTF-8</Encoding>
  <BufferedIO>false</BufferedIO>
  <ImmediateFlush>true</ImmediateFlush>
  <layout class="ch.qos.logback.classic.PatternLayout">
   <Pattern>
    %date [%thread] %-5level %logger{35} - %msg%n
   </Pattern>
  </layout>
 </appender>
 <root>
  <appender-ref ref="OFLA" />
 </root> 
 <logger name="org.red5.demos.oflaDemo2">
  <level value="DEBUG" />
 </logger>  
</configuration>

・web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 
   xmlns="http://java.sun.com/xml/ns/j2ee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
   version="2.4"> 
 
    <display-name>oflaDemo2</display-name>
 
 <context-param>
  <param-name>webAppRootKey</param-name>
  <param-value>/oflaDemo2</param-value>
 </context-param>
 
    <listener>
        <listener-class>org.red5.logging.ContextLoggingListener</listener-class>
    </listener>
    
    <filter>
        <filter-name>LoggerContextFilter</filter-name>
        <filter-class>org.red5.logging.LoggerContextFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>LoggerContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    <servlet>
  <servlet-name>rtmpt</servlet-name>
  <servlet-class>org.red5.server.net.rtmpt.RTMPTServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 
    <servlet>
     <display-name>SecurityTest</display-name>
     <servlet-name>SecurityTest</servlet-name>
     <servlet-class>org.red5.demos.oflaDemo2.SecurityTest</servlet-class>
    </servlet>
    
 <servlet-mapping>
  <servlet-name>rtmpt</servlet-name>
  <url-pattern>/fcs/*</url-pattern>
 </servlet-mapping>

 <servlet-mapping>
  <servlet-name>rtmpt</servlet-name>
  <url-pattern>/open/*</url-pattern>
 </servlet-mapping>

 <servlet-mapping>
  <servlet-name>rtmpt</servlet-name>
  <url-pattern>/close/*</url-pattern>
 </servlet-mapping>

 <servlet-mapping>
  <servlet-name>rtmpt</servlet-name>
  <url-pattern>/send/*</url-pattern>
 </servlet-mapping>

 <servlet-mapping>
  <servlet-name>rtmpt</servlet-name>
  <url-pattern>/idle/*</url-pattern>
 </servlet-mapping>
 
 <servlet-mapping>
  <servlet-name>SecurityTest</servlet-name>
  <url-pattern>/securitytest</url-pattern>
 </servlet-mapping>
    
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Forbidden</web-resource-name>
            <url-pattern>/streams/*</url-pattern>
        </web-resource-collection>
        <auth-constraint/>
    </security-constraint>

</web-app>

・red5-web.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                            
    http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">

 <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <property name="location" value="/WEB-INF/red5-web.properties" />
 </bean>

 <bean id="web.context" class="org.red5.server.Context" autowire="byType" />

 <bean id="web.scope" class="org.red5.server.scope.WebScope" init-method="register">
  <property name="server" ref="red5.server" />
  <property name="parent" ref="global.scope" />
  <property name="context" ref="web.context" />
  <property name="handler" ref="web.handler" />
  <property name="contextPath" value="${webapp.contextPath}" />
  <property name="virtualHosts" value="${webapp.virtualHosts}" />
 </bean>

 <bean id="web.handler" class="org.red5.demos.oflaDemo2.Application" />
<!--
 <bean id="web.handler" class="org.red5.server.script.rhino.RhinoScriptFactory">
  <constructor-arg index="0" value="classpath:main.js"/>
  <constructor-arg index="1">
   <list>
        <value>org.red5.server.api.IScopeHandler</value>
        <value>org.red5.server.adapter.IApplication</value>
     </list>
  </constructor-arg>
  <constructor-arg index="2">
      <value>org.red5.server.adapter.ApplicationAdapter</value>
  </constructor-arg>
 </bean>

 <bean id="web.handler" class="org.springframework.scripting.jruby.JRubyScriptFactory">
  <constructor-arg index="0" value="classpath:main.rb"/>
  <constructor-arg index="1">
   <list>
    <value>org.red5.server.api.IScopeHandler</value>
    <value>org.red5.server.adapter.IApplication</value>
   </list>
  </constructor-arg>
 </bean>

 <bean id="web.handler" class="org.red5.server.script.groovy.GroovyScriptFactory">
  <constructor-arg index="0" value="classpath:main.groovy"/>
  <constructor-arg index="1">
   <list>
    <value>org.red5.server.api.IScopeHandler</value>
    <value>org.red5.server.adapter.IApplication</value>
   </list>
  </constructor-arg>
 </bean>

 <bean id="web.handler" class="org.red5.server.script.jython.JythonScriptFactory">
  <constructor-arg index="0" value="classpath:main.py"/>
  <constructor-arg index="1">
   <list>
        <value>org.red5.server.api.IScopeHandler</value>
        <value>org.red5.server.adapter.IApplication</value>
     </list>
  </constructor-arg>
        <constructor-arg index="2">
            <list>
                <value>One</value>
                <value>2</value>
                <value>III</value>
            </list>
        </constructor-arg>
 </bean>
-->
    <bean id="demoService.service" class="org.red5.demos.oflaDemo2.DemoService" />
<!--
 <bean id="demoService.service" class="org.red5.server.script.rhino.RhinoScriptFactory">
  <constructor-arg index="0" value="classpath:demoservice.js"/>
  <constructor-arg index="1">
   <list>
        <value>org.red5.demos.oflaDemo2.IDemoService</value>
     </list>
  </constructor-arg>
  <constructor-arg index="2">
      <value>org.red5.demos.oflaDemo2.DemoServiceImpl</value>
  </constructor-arg>
 </bean>

 <bean id="demoService.service" class="org.springframework.scripting.jruby.JRubyScriptFactory">
  <constructor-arg index="0" value="classpath:demoservice.rb"/>
  <constructor-arg index="1">
   <list>
        <value>org.red5.demos.oflaDemo2.IDemoService</value>
     </list>
  </constructor-arg>
 </bean>

 <bean id="demoService.service" class="org.red5.server.script.jython.JythonScriptFactory">
  <constructor-arg index="0" value="classpath:demoservice.py"/>
  <constructor-arg index="1">
   <list>
    <value>org.red5.demos.oflaDemo2.IDemoService</value>
   </list>
  </constructor-arg>
  <constructor-arg index="2" ref="web.handler"/>
 </bean>
-->

<!-- Uncomment this if you are using scripting

 <bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
-->

</beans>

・red5-web.properties
webapp.contextPath=/oflaDemo2
webapp.virtualHosts=*, localhost, localhost:8088, 127.0.0.1:8088, 192.168.10.22


ソースのコードの変更が終わったら、ビルドを実行します。
oflaDemo2プロジェクトを右クリックして、Run AS > Java Application を押します。


実行後に、エラーが発生していなければ問題なしです( ´∀`)bグッ!

ビルドしたファイルをRed5のwebappsにoflaDemo2ディレクトリをそのままコピーします。



コピー後のwebappsの構成は次のようになります。



サンプルデモのoflaDemoではstreamsというディレクトリに、
動画ファイルなどが配置されていて、それを利用しています。

そのため、oflaDemo2でもそのディレクトリが必要となりますので、
oflaDemoからstreamsというディレクトリをコピーします。

最終的なoflaDemo2の構成はつぎようになります。


これで全て完了しましたので、Red5を起動します!

問題なく起動が出来たら、次のURLにアクセスして動作を確認します。
※事前にRed5のサンプルデモがインストールされていること。

http://Red5サーバーIPまたはドメイン:Red5サーバーポート番号/demos/ofla_demo.html

たとえばIPアドレスが「192.168.10.22」でポート番号が「5080」だった場合
http://192.168.10.22:5080/demos/ofla_demo.html

画面が開いたら、右上の枠に、「rtmp://192.168.10.22/oflaDemo2」と入力して
connectを押してください。



connectを押した後に、右上の5のマークが緑色の変われば正常に接続が完了した印になります。
また、成功すると、左上の「library」の枠に、動画ファイルのリストが表示されます。



表示された動画ファイルをクリックすると、再生が始まります。


キタ――(゚∀゚)――!!

これで、無事にRed5プロジェクトのコンパイルが完了しました!( ´∀`)bグッ!


以上です(`・ω・´)ゞビシッ!!

参考URL

0 件のコメント:

コメントを投稿