JSR 309 Media Server Control APIによるマルチメディア・アプリケーション開発の迅速化

Marc Brandt、Tomas Ericson、Alain Comment著

Oracle Communications Converged Application Serverで稼働するJSR 309 Reference Implementation Driverを使用し、HP OpenCall Media Platformにアクセスする、SIP Servlet電話会議アプリケーションを構築する方法を学びます。

2010年4月公開

ダウンロード:
 Oracle Communications Converged Application Server
 電 話会議アプリケーションのサンプル

ここ数年、リッチなマルチメディア通信アプリケーションをデプロイするためのアーキテクチャの進化により、アプリケーション・ロジックとメディア処理とを 分散できるようになりました。 このわかりやすい例が、3GPP IMS MRFデプロイメント・アーキテクチャの進化と、IETF SIPおよびMedia Server Controlプロトコルによるアプリケーション・サーバーとメディア・サーバーの分離モデルのサポートです。

簡単に説明すると、オープン・スタンダードの登場により、このようなアプリケーション・サーバーとメディア・サーバー、すなわちAS- MSアーキテクチャを相互に運用できるデプロイメントが実現します。 オラクルとHPはともにオープン・スタンダードを推進し、採用することを宣言しました。 こうしたデプロイメント・モデルを成功させる鍵は、デプロイされるアプリケーションのプログラミングを簡単にすることです。

JSR 309 APIの提 供するプログラミング・モデルは柔軟なもので、基盤となるAS-MS分離の豊富な機能に適合します。 JSR 309 APIは、メディア・サーバーへのマルチメディア機能の委任をサポートします。この例としては、VoiceXMLの使用や、特にRFC 5022 MSCMLやIETF Media Server Controlプロトコル(RFC 5167、5552、5567を参照)などのプロトコルを介したメディア・サーバー処理による詳細な制御の実現などが挙げられます。

図1は、近年、3GPPによって進化したMRFアーキテクチャが、機能の豊富なメディア・サーバーのデプロイメントをどのようにサポー トするかを示しています。メディア・サーバーは、IP Multimedia Core Network Subsystem(Release 8の3GPP TS 23.002ネットワーク・アーキテクチャで導入)内のCr参照ポイントを経由し、オープン・スタンダードのMedia Server Controlインタフェースを通じてデプロイされます。

新しいスタンダードがマッピングされた新しいCr参照ポイントの導入(3GPP TS 23.218より抜粋)
図1 新しいスタンダードがマッピングされた新しいCr参照ポイントの導入(3GPP TS 23.218より抜粋)


HPは、3GPPではTR 24.880の報告担当者としてこれらの進化を積極的に推進するとともに、IETF MediaCtrlの共同編集者およびW3C Voice Browser Working Groupの共同議長として、分散メディア・サーバー制御のスタンダードの策定に貢献しています。

JSR 309の標準化: Javaによるメディア・サーバー・リソースの制御

JSR 289 SIP Servlet 1.1 APIの仕様リードであったオラクルと、メディア・サーバーのデプロイメント・モデルおよび制御プロトコルの多様性を認識していたHPは、2007年に協 力してJSR 309 APIをJavaプラットフォームに推進しました。その結果、JSR 309 APIは広範なプロトコルおよび委任モデルをアプリケーション開発者に透過的にサポートするプログラミング・モデルになりました。

図2は、アプリケーション・サーバーおよびメディア・サーバーのオープン・スタンダードに準拠した一般的な分散デプロイメント内の標準 化環境における、このAPIの位置付けを示したものです。


図2 Media Server Control環境におけるAPIおよびプロトコルのオープン・スタンダードの位置付け


JSR 309のおもな利点は、基礎となるMedia Server Controlプロトコルに依存しないJava APIを提供する点にあります。 メディア・サーバー仕様は、JDBCでデータベース仕様が抽象化されるのと似た方法でJSR 309 Driverによって処理されます。これによりアプリケーション開発者は、メディア・サーバーのベンダーに関係なく、JSR 309 APIを使用して透過的にプログラミングできます。 また、オペレーターおよびサービス・プロバイダーは、アプリケーションを再記述する必要なく、異なるメディア・サーバーを簡単に使用できます。

JSR 309では、AS-MSデプロイメント・モデル間のアプリケーション・プログラミングが簡素化され、移植性が保証される一方で、ドライバ実装内の既存また は新しい標準プロトコルが柔軟にサポートされます。

HPが提供するJSR 309 Reference Implementationは、SIP Servletテクノロジーおよび広範にデプロイされているプロトコルIETF MSCMLを使用して実装されるドライバです。 IETF MediaCtrlも上記の図に示されており、AS-MSの相互運用性のための将来のオープン・スタンダード・プロトコルとして位置付けられています。

JSR 309の概要

JSR 309 Media Server Control API 1.0により、join処理を通してメディア・サーバー・リソースとメディア・ストリームのトポロジを制御する非常に柔軟なオブジェクト・モデルが定義さ れます。

JSR 309の対象となるのは、次のようなアプリケーションです。

  • MediaGroup、Player、Record、SignalDetectorの各オブジェクトを使用した音声自動応答 (IVR)。 音声または映像のプロンプトおよび記録、DTMFのプロンプトおよび収集、VoiceXMLサーバーおよびVoiceMailサーバーとのやり取り。
  • MediaMixerオブジェクト(音声、映像、レイアウト)を使用した会議。
  • 上記とその他のJSR 309コア・オブジェクト機能との組合せ(マルチメディアIVR、リング・バック、ビデオ・モニタリング、コール・センター/コンタクト・センター)。

図3は、オブジェクト・モデルのインタフェースの一部を示したものです。これらは、電 話会議アプリケーションのサンプルを通じて使用されます。

電話会議アプリケーションで一般的に使用されるJSR 309のコア・オブジェクト
図3 電話会議アプリケーションで一般的に使用されるJSR 309のコア・オブジェクト


JSR 309は、アプリケーション・サーバーとメディア・サーバーの分離されたデプロイメント・モデルに適合するように設計されています。このモデルには、以下 の特徴があります。

  • アプリケーションは、SIPシグナリングを通じてエンド・ポイント間のマルチメディア中継点を接続し、処理します。
  • メディア・サーバーは、JSR 309 APIを通じてアプリケーションによって制御され、SDPプロパティに記述された関連するメディア・ストリームを処理します。

図4は、この記事で説明する電話会議アプリケーションで使用されるJSR 309のデプロイメント・アーキテクチャを表しています。

一般的なJSR 309デプロイメント・アーキテクチャ
図4 一般的なJSR 309デプロイメント・アーキテクチャ


Oracle Communications Converged Application Server内にデプロイされる電話会議アプリケーションでは、HP OpenCall JSR 309 Reference ImplementationおよびHP OpenCall Media Platform(HP OCMP)が使用されています。

電話会議アプリケーションの記述およびセットアップ

電話会議アプリケーションには、分散環境におけるJSR 309およびSIP Servlet APIの機能と柔軟性がよく表れています。 通常、商業アプリケーションでは、はるかに多くのJSR 309 APIの機能が使用されますが、このサンプル・アプリケーションでは、会議で複数の参加者を接続して組み合わせるために必要なコール・コントロール・ロ ジックおよびメディア処理の機能を説明しています。

電話会議アプリケーションをデプロイしてテストするには、Deploying and Running the Conferencing Applicationを参照してください。

設計の概要

次の図は、アプリケーションで使用されるおもなコンポーネントを示したものです。

高度な電話会議アプリケーションのアーキテクチャ
図5 高度な電話会議アプリケーションのアーキテクチャ


通常、ユーザーは、SIP電話を使用して電話会議アプリケーションに接続します。 ユーザーは、会議ID番号を入力するように要求され、ユーザー名を記録するように勧められます。 ここで記録した名前はアナウンスメントとして再生され、後でWebインタフェースを通して検索できるようになります。 会議に参加するには、パスワードが必要です。 パスワードは、このサンプル・ユースケースの実用的な理由により、最初の参加者が設定できます。 会議中は、参加者は回線をミュートにしたり、ミュートを解除したりできます。 参加者のミュートなどのアプリケーション・インタラクションは、SIP電話のDTMFを通して、またはWebインタフェースで行います。 これは、アプリケーションで、入力ソースの異なる同じメディア機能を制御できる方法を示しています。

電話会議アプリケーション・コードの説明

ここでは、一部のアプリケーション・フローおよびコードを説明することにより、JSR 309の使用について示します。 SIP Servlet APIおよびJSR 309 Media Server Control APIの詳細については、参考資料の項を参照してください。

電話会議アプリケーションは、いわゆる"converged application"(融合アプリケーション)で、HTTP ServletとSIP Servletを単一のWebアーカイブ(warファイル)に組み合わせたものです。 また、電話会議アプリケーションは、JSR 309 APIを起動することでメディア・リソースを制御しています。 SIP Servletコードは、エンド・ポイント(会議の参加者)があるコール・コントロールの処理を担います。 HTTP ServletおよびJSPを使用して実装された単純なWebインタフェースから、ユーザーは進行中の会議を監視および制御できます。これは、同一のアプ リケーション環境に、SIP、HTTPおよびMedia Controlの各機能が融合されていることを示します。

次の図は、さまざまなクラスのアプリケーションを示す詳細なクラス図です。

詳細なクラス図
図6 詳細なクラス図 [クリックして拡大]


ConferenceServletの概要

SIP Servlet ConferenceServletは、会議参加者のターミナルとアプリケーション・サーバー間のSIPシグナリングを処理し、受信するSIPコールなど に応答します。

                               
// Common factory for JSR 309 objects used by all service classes
public static MsControlFactory theMsControlFactory;

ConferenceServletの初期化の際に、MsControlFactoryインスタンスが "com.hp.opencall"という名前のHP Reference Implementation Driverから取得されます。 このMsControlFactoryインスタンスは、JSR 309オブジェクトを作成するためにアプリケーション全体で使用されます。

                               
public void init() throws ServletException {
try {...
theMsControlFactory =
DriverManager.getFactory("com.hp.opencall", info);
...} …

getFactoryメソッドが呼び出されると、DriverManagerはリクエストされたドライバを参照し、そこから MsControlFactoryを取得します。 JSR 309 APIの一部のDriverManagerクラスでは、ドライバ・パッケージは自動的にロードされて登録されます(ドライバのパッケージングに依存)。

また、ConferenceServletは、ParticipantオブジェクトおよびConferenceSessionオブジェ クトを管理するConferenceManager(confManager)をインスタンス化します。

最初のSIP INVITEを受信すると、新しいParticipantがインスタンス化され、SDP折衝を初期化するNetworkConnectionの作成が開始 されます。 SIP ACKが受信されると、参加者のインタラクションが開始し、参加者に会議IDを入力するように求めます。SIP BYEを受信すると、参加者は会議から退席します。

                               
…doInvite(SipServletRequest req) ...{
// Create a new Participant
ConferenceManager.getInstance().addParticipant(
userId, req.getRawContent(),
req.getSession().getApplicationSession().getId());... }

… doAck(SipServletRequest req) ... {
// Launch the media service
... participant.start(); ... }

doBye(SipServletRequest req) ... {
// Terminate the service
... participant.release();
// Send 200 OK to the UA
...}

ConferenceSessionの概要

このクラスは、固有のJSR 309 MediaSession、MediaMixer、およびMediaGroupを保持する会議室をモデリングします。 MediaGroupは、Conferenceに対してアナウンスメントを再生するために使用します。

                               
        // JSR 309 objects
private final

MediaSession
mMediaSession;
private final

MediaMixer
mMediaMixer;
private final

MediaGroup
mMediaGroup;

各Conferenceは、会議ID(ConfID)とパスワードがあり、ParticipantとOrganizerを保持します。 Participantを見てみましょう。

                               
       // Conference identifier and participants list
private final String confId;
private List<Participant> mParticipants;
private Participant mOrganizer;
private String mPassword;

ConferenceSessionがインスタンス化されると、ConferenceServletが初期化された際に DriverManagerを通して取得されたMsControlFactoryから、JSR 309オブジェクトが作成されます。

                               
public ConferenceSession(String confId, Participant aParticipant,

ConferenceServlet aServlet) …{

        mMediaSession = ConferenceServlet.theMsControlFactory.

createMediaSession
();
mMediaMixer = mMediaSession.

createMediaMixer
(MediaMixer.

AUDIO
);
mMediaGroup =
mMediaSession.

createMediaGroup
(MediaGroup.

PLAYER
);
mMediaGroup.

join
(Direction.

SEND
, mMediaMixer);


        }


最初のステップで、theMsControlFactoryのcreateMediaSession()を呼び出す MediaSessionが作成されます。 MediaSessionは、電話会議アプリケーションで使用されるメディア・オブジェクトのファクトリでありコンテナです。

初期化された各ConferenceSessionに、AUDIO-only MediaMixerおよびPLAYER-only MediaGroupが割り当てられます。 MediaGroupは、会議でメディアを実行できるようにSENDモードのMediaMixerに結合されます。

アプリケーションを拡張して会議を記録するには、MediaGroupの構成を PLAYER_RECORDER_SIGNALDETECTORにし、MediaGroupをDUPLEXモードで結合する必要があります。 そして、record()メソッドは、記録されたファイルの送信を可能にするHTTP URLとともに使用する必要があります。

Participantがこの会議に参加するか会議から退席すると、ConferenceSessionによりアナウンスメントが再生 されます。 たとえば、誰かが会議を退席した際に残りのParticipantにアナウンスメントを再生するには、次のようにします。

  • まず、再生するファイルに参照を作成します。
                               
   public void removeParticipant(Participant participant) {
...{
String[] fileURLs =
new String[] { participant.getRecordingURI().toString() +
"

&disconnected=true
",
Participant.getPromptDirPath() +
"HasLeftTheConference.wav" };
}; ...
playAnnouncement(fileURLs);
… }
  • 次に、このConferenceでMediaMixerに接続されているMediaGroup上のファイルを再生します。
                               
public void playAnnouncement(String[] fileURLs) {
… mMediaGroup.

getPlayer
().

play
( streamIDs,
null,
Parameters.NO_PARAMETER);
… }

再生の最後に、PlayerがPLAY_COMPLETEDイベントを送信します。 アプリケーションは、PlayerのMediaEventNotifierインタフェース上でMediaEventListenerを登録することによ り、このイベントを検出します。

Participantの概要

このクラスは、会議参加者をモデリングし、参加者のインタラクションに対応するステート・マシンを実装します。

参加者のステート・マシン図
図7 参加者のステート・マシン図


各Participantは、独自のJSR 309 MediaSession、NetworkConnection、およびMediaGroupを保有します。 NetworkConnectionは、そのSdpPortManagerとともに、ユーザー・エージェントとメディア・サーバー間のRTPトラフィック およびSDP構成を処理します。 MediaGroupは、新規のParticipantが参加する際の会議IDまたはパスワードの取得、プロンプトの実行、参加者名の記録などの、参加者 とのDTMFインタラクションに使用されます。

                               
private final

NetworkConnection
mNetworkConnection;
private final

SdpPortManager
mSdpPortManager;
private final

MediaGroup
mMediaGroup;
private final

MediaSession
mMediaSession;

ParticipantのNetworkConnectionおよびMediaGroupの初期化

Participantは、ConferenceServletから最初のSIP INVITEを受信したときに初期化されます。

                               
public Participant(final SipServletRequest req) ... {…}

次のJSR 309オブジェクトが作成されます。

                               
mMediaSession =   
    ConferenceServlet.theMsControlFactory.

createMediaSession
();
myNetworkConnection =  
    myMediaSession.

createNetworkConnection
(NetworkConnection.

BASIC
);
mySdpPortManager = myNetworkConnection.

getSdpPortManager
();
myMediaGroup = myMediaSession.

createMediaGroup
(
               MediaGroup.

PLAYER_RECORDER_SIGNALDETECTOR
);

通常のNetworkConnectionは、デフォルトの構成を使用して作成されます。 作成される参加者のMediaGroupには、Player、RecorderおよびSignalDetectorリソースが含まれます。

MediaGroupのリソース上で起動されたメディア処理の完了を通知させるには、イベント・リスナーを登録する必要があります。 通常、イベント・リスナーは、再生処理、記録処理、またはDTMF収集処理の完了を取得します。

                               
myMediaGroup.

getPlayer
().

addListener
(new
ConfListener<PlayerEvent>());
mMediaGroup.

getRecorder
().

addListener
(new
ConfListener<RecorderEvent>());
mMediaGroup.

getSignalDetector
().

addListener
(new
ConfListener<SignalDetectorEvent>());

新しいNetworkConnectionがMediaGroupに結合されます。 これはSDP折衝が完了する前に実行されることに注意してください。 プロンプトの実行、DTMFの記録または検出を可能にするために、join処理はDUPLEXで行います。

                               
mNetworkConnection.

join
(Direction.

DUPLEX
, mMediaGroup);

ユーザー・エージェントから受信したSDPオファーは、SdpPortManagerに送信されます。

                               
mSdpPortManager.

processSdpOffer
(sdpOffer);
SDP折衝の呼出しフロー
図8 SDP折衝の呼出しフロー


メディア・サーバーからSDPアンサーを処理するために、イベント・リスナーをSdpPortManagerに登録します。 SdpPortManagerからイベントが正しく受信されると、メディア・サーバーから取得されたSDPアンサーとともに200OKが送信されます。

                               
mSdpPortManager.addListener(new
MediaEventListener() {...}
{
If(event.getEventType().equals(

SdpPortManagerEvent.ANSWER_GENERATED
)) {
// The NetworkConnection has been setup properly.
// Send a 200 OK, with negotiated SDP from the Media Server attached.
ConferenceServlet.sendResponse(sipAppSessionId,
SipServletResponse.SC_OK,
"application/sdp", event.getMediaServerSdp());
}

参加者が加わるときのメディア・インタラクション

参加者と会議の間のインタラクションは、private enum State { }というjava enumを使用してParticipantに実装されたステート・マシン・パターンを通して処理されます。 高水準のステート・マシンは、図7に示しています。

次の図は、会議に参加する際のユーザー・インタラクションを示したものです。

会議に加わる参加者の呼出しフロー
図9 会議に加わる参加者の呼出しフロー


参加者が接続されると、最初のインタラクションは、プロンプトおよび収集処理を通じて会議IDを取得することです。 これは、receiveSignal()処理およびSignalDetector.PROMPT機能を使用することによって実現します。 初期タイムアウトおよび桁間タイムアウトも設定されており、バージインが有効化された状態で最大4桁が収集されます。このとき、ユーザーが桁の入力を開始 するとPROMPTは停止されます。 これは、ステートEnterConfIdの次のエントリ・アクションによって実行されます。

                               
{ Parameters params = 
             ConferenceServlet.theMsControlFactory.

createParameters
();
params.put(SignalDetector.

INITIAL_TIMEOUT
, 5000);
params.put(SignalDetector.

INTER_SIG_TIMEOUT
, 5000);
URI prompt = URI.create(getPromptDirPath() +
                             "PleaseEnterYour4DigitConferenceID.wav");
params.put(SignalDetector.

PROMPT
, prompt);
part.mMediaGroup.

getSignalDetector
().

receiveSignals
(
                             4, null,
                             new RTC[] { //barge-in
        new RTC(SignalDetector.

DETECTION_OF_ONE_SIGNAL
, Player.

STOP
)},
                             params);
}

ステートEnterConfIdは、既存のConferenceSessionを取得または新規作成するために、対応する SignalDetectorEventを受信し、収集された会議IDを処理します。

                               
if (event.getEventType() ==
               SignalDetectorEvent.

RECEIVE_SIGNALS_COMPLETED
) {...}

SignalDetectorは、ステートEnterConfPwdでParticipantに会議パスワードを入力するように要求す るためにも同様に使用されることに注意してください。

別のインタラクションでは、Recorderを使用して参加者の名前が記録されます。 これは、ステートRecordingNameで実行されます。 record()処理はPROMPTパラメータとともに使用され、バージインは、Run Time Control(RTC)を使用して有効化されています。これにより、ユーザーが'#'を押した際に記録が中断されるようになります。

                               
{ Parameters params = 
   ConferenceServlet.theMsControlFactory.createParameters();
   URI prompt = URI.create(getPromptDirPath() +    
               "PleaseSayYourNameEndWithHash.wav");
   params.put(Recorder.

PROMPT
, prompt);
   params.put(SignalDetector.

PATTERN[0]
, "#");
   part.mMediaGroup.getRecorder().

record
(
      part.getRecordingURI(),
      new RTC[] { // barge-in
      new RTC(SignalDetector.

DETECTION_OF_ONE_SIGNAL
, Player.

STOP
),
        // stop recording key
      new RTC(SignalDetector.

PATTERN_MATCH[0],
Recorder.

STOP
)},
      params);
}

ステートRecordingNameは、対応するRecorderEventを受信し、参加者がイベント型および修飾子に基づいた何か を記録したかどうかを認識します。

                               
...if (event.getEventType() == RecorderEvent.RECORD_COMPLETED) {
if (event.getQualifier() == RecorderEvent.SILENCE) {
...}… else if (event.getQualifier() == ResourceEvent.RTC_TRIGGERED
&& event.getRTCTrigger() ==
SignalDetector.PATTERN_MATCH[0]) {...

参加者が会議IDを入力し、名前を記録し、会議パスワードを入力すると、参加者は会議に加わります。 これは、2つのステップで行われます。 最初に、参加者に対してウェルカム・プロンプトが実施されます。 それから、参加者は会議に加わり、新しい参加者を通知するウェルカム・プロンプトが会議全体にアナウンスされます。 これは、ステートWelcomeで実行されます。

                               
{... // use the participant's MediaGroup
part.mMediaGroup.getPlayer().

play
(
URI.create(getPromptDirPath() + "PutIntoSession.wav"),
null, Parameters.NO_PARAMETER);

part.mNetworkConnection.

join
(Direction.

DUPLEX
,
confSession.getMediaMixer());

// play an announcement to the conference using conference's MediaGroup
confSession.playAnnouncement(fileURLs);

会議中における参加者とのメディア・インタラクション

参加者が会議に加わると、キーを押してDTMFをトリガーすることにより、ミュートやミュート解除などのいくつかの機能を制御できま す。 これを行うために、各参加者は、会議と独自のMediaGroupの両方に参加していることに注意してください。

                               
// upon Participant initialization
mNetworkConnection.

join
(Direction.

DUPLEX
, mMediaGroup);

// upon Participant joining the Conference
part.mNetworkConnection.

join
(Direction.

DUPLEX
,
confSession.getMediaMixer());

会議とMediaGroupの2つに参加する結果として、ParticipantのメディアがConferenceとの二重通信を行い ますが、参加者から受信する入力は参加者のMediaGroupに送信されるため、この単一の参加者からDTMFを検出できます。 ConferencingまたはConferenceMutedステートの間、receiveSignal()処理は常に参加者のMediaGroupで アクティブ化されているため、参加者がキーを押すことによってトリガーされるすべてのDTMFを受信できます。

                               
part.mMediaGroup.getSignalDetector().

receiveSignals
(

1
, null, null, null);

参加者がキー'6'を入力すると、参加者はミュート状態になります。 次のjoinによって、参加者のNetworkConnectionがMediaGroupに接続され、MediaMixerからは分離されます。 そして、MediaGroupは、ミュート通知(参加者に対してのみ)を行うために使用されます。 通知が行われると、参加者はRECVモードのみでMediaMixerに戻り、会議を聴き続けます。

                               

private void mute(Participant part) ... {
    part.mNetworkConnection.

join
(Direction.

DUPLEX
, part.mMediaGroup);
    part.mMediaGroup.getPlayer().

play
(URI.create(getPromptDirPath() +
                                       "MuteOn.wav"), null,
                                       Parameters.NO_PARAMETER);

part.mNetworkConnection.

join
(Direction.

DUPLEX
,
                 confSession.getMediaMixer());

参加者はMediaGroupに接続されたままであるため、DTMFはアクティブなreceiveSignals()処理によってまだ 検出できることに注意してください。

ConferencingMutedステートの間、参加者はキー'9'を押すことにより、参加者のMediaGroupの同一の SignalDetectorを使用してミュートを解除できます。 このイベントを受け取ると、Participantは、ミュート解除の通知を行うためにMediaGroupに結合され、play()処理の最後に DUPLEXモードでMediaMixerに結合されます。 ここで、参加者はステートConferencingに戻りました。

                               

part.myNetworkConnection.

join
(Direction.

DUPLEX
, part.myMediaGroup);
part.myMediaGroup.getPlayer().play(URI.create(getPromptDirPath() +  
                     "MuteOff.wav"), null, Parameters.NO_PARAMETER);>

part.myNetworkConnection.

join
(Direction.

DUPLEX
,
                          part.myConferenceSession.getMediaMixer());

オーガナイザーとしての参加者とのメディア・インタラクション

これらのインタラクションは、ステート図に表示されます。 JSR 309を使用した以下のような他の例を見るには、Organizerロールに関連するParticipantステートのソース・コードと、HTTP Servletを参照することをお薦めします。

  • 参加者が、オーガナイザーを待つ間に保留の音楽を聴く
  • オーガナイザーが会議パスワードを設定する
  • Webインタフェースから参加者をミュート/ミュート解除/分離する

Media Server Control APIの進化

デプロイメントは市販のアプリケーション・サーバーおよびメディア・サーバーに基づいていますが、このサンプル・アプリケーションで は、実際のネットワークにデプロイされた場合の完全分散ソリューションのスケーラビリティおよび可用性に関しては、対応していない点がいくつかあります。 アプリケーション・サーバーまたはメディア・サーバーの選択、ロードバランシング、リソース仲介、リソース予約、可用性管理といったほとんどの機能は、通 常はデプロイメント・アーキテクチャを通じて処理されます。

JSR 309 Media Server Control APIのバージョン1.0では、実装の差別化の一部を成し、可能な限りプログラマーに透過的な状態を維持するためのこうした側面を処理する追加機能があり ません。 ただし、これらの運用機能は、デプロイメントに基づいてJSR 309エキスパート・グループによって特定されており、メディア・サーバー機能の拡張については、このAPIの進化中に研究されることになります。

APIの目的は、異なるMS上で使用可能な特定のメディア機能のポータブル・プログラミング・モデルをサポートすることです。ただし、 すべてのMSが異なる機能をサポートする、またはJSR 309で定義されるすべての機能を一度にサポートするわけではないことも考慮に入れています。 アプリケーションでは、SupportedFeaturesインタフェースを利用して、どの特定の機能が特定のJSR 309 Driver実装をサポートしているかを動的に検出できます。 アプリケーションは、新しいプロトコルとともに進化することが期待されており、実際のアプリケーション・プログラミングを行うことにより、この機能が向上 します。

JSR 309 1.0は、豊富なレイアウト・レンダリングによってビデオ会議に対応する一連の機能をサポートしています。 さらに映像機能が豊富でインタラクティブなアプリケーションが設計されるにつれ、現行のインタフェースから進化した共通の標準APIが必要とされて、新し い機能が明らかになると考えられます。 1つの例は、音声および映像に加えて、メディア・ストリーム・タイプ・メッセージ(RFC 4975 MSRPメッセージ・セッション)を使用した、さらに高度な機能のサポートです。

JSR 309 1.0の仕様は、メディア・サーバー機能に対応する非常に柔軟な一連のコア・オブジェクトに重点を置いています。 JSR 309エキスパート・グループの設立時に、すでにコンポジット操作の必要性は確認されていました。 PromptおよびRecordや、PromptおよびCollectなどのコンポジット操作は、すでにMediaGroupの運用に含まれていました。 追加項目としては、会議でのすべての参加者の一括ミュート、補足会議の対処などが考えられます。これらのコンポジット処理はコア・オブジェクト上で開発で きますが、これから広範に使用されるコンポジット処理を標準化することが重要でしょう。

結論

この記事では、JSR 309 Media Server Control APIおよびJava SIP Servletの新しいテクノロジーに基づいて、電話会議アプリケーションのサンプルを紹介しました。 ここでは、ユーザー・エージェント、アプリケーション・サーバーおよびメディア・サーバー間のエンド・ツー・エンドのフローを説明する完全なアプリケー ションの例を提示しました。 ここでは、MSCMLや、市場で入手可能な、または新しいIETF標準として登場している他のプロトコルなどの基礎になるMedia Server Controlプロトコルの知識を必要とせずにアプリケーションを記述することの価値と容易さを表しています。

電話会議アプリケーションのビジネス・ロジックすべてのうち約1,500行のJavaコードによって、SIPコール・コントロールおよ びWebインタフェースが実装されました。 これは、JSR 309 APIによってアプリケーション開発者がビジネス・ロジックとユーザー・インタフェースの設計に重点を置くことができ、JSR 309ドライバがメディア・サーバーのインタラクションを効率的に処理できることを示しています。

電話会議アプリケーションは、JSR 309を使用することによって簡単に強化できます。以下に例を示します。

  • VoiceXMLの使用は、参加者のインタラクションに対応するためのオプションになります。 JSR 309は、VxmlDialogインタフェースを通してVoiceXMLリソースの制御をサポートします。
  • この電話会議アプリケーションは音声のみに対応していますが、映像機能のサポートを簡単に追加できます。VideoLayout を設定する追加機能はJSR 309によってサポートされており、アプリケーションに簡単に追加できます。
  • Active Talkerの検出を追加し、どの参加者がWebインタフェース上で話しているかを表示します。

電話会議アプリケーションのサンプルでは、SIP Servlet 1.1やMedia Server Control 1.0などのオープン・スタンダードのJava APIを使用して、分散アプリケーション・サーバー-メディア・サーバー・アーキテクチャ内のマルチメディア・アプリケーションを開発およびデプロイする ことの価値と実現可能性が示されています。

参考資料


Marc Brandtは、HP Software & Solutions CMS、Communications and Media Solutionsのマスター・テクノロジストです。 HP CMSがメンバーになっているさまざまな組織やフォーラムにおいて、業界標準を調整する活動を行ってきました。 2007年1月の開始以来、JSR309の共同リーダーを務めています。

Tomas Ericsonは、オラクルのテクニカル・スタッフの主要メンバーです。 通信領域全般におけるJavaサーバー・プログラミング、特にIMS/SIP//VoIP/Presenceの分野で長い経験があります。 JSR 309の仕様の作成に協力し、JSR 289(SIP Servlet API)エキスパート・グループのメンバーです。

Alain Commentは、HP Software & Solutions CMS、Communications and Media Solutionsのシニア開発者です。 HP OpenCall Media Platformのインタフェースと内部を先導し、JSR 309仕様において主要な役割を果たしました。