翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
コードの確認
このセクションでは、Java ライブラリとテストコードを検証し、ライブラリに含まれるツールを独自のコードで使用する方法について学習します。
Kinesis ビデオストリームパーサーライブラリには、次のツールが含まれています。
StreamingMkvReader
このクラスは、ブロックしない方法でストリームから指定されたMKV要素を読み取ります。
次のコード例 (FragmentMetadataVisitorTest
から) は、Streaming MkvReader
を作成、使用して inputStream
と呼ばれる入力ストリームから MkvElement
オブジェクトを取得する方法を示しています。
StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(new InputStreamParserByteSource(inputStream)); while (mkvStreamReader.mightHaveNext()) { Optional<MkvElement> mkvElement = mkvStreamReader.nextIfAvailable(); if (mkvElement.isPresent()) { mkvElement.get().accept(fragmentVisitor); ... } } }
FragmentMetadataVisitor
このクラスはフラグメント (メディア要素) のメタデータを取得し、コーデックプライベートデータ、ピクセル幅、ピクセル高さなどのメディア情報を含む個々のデータストリームを追跡します。
次のコード例 (FragmentMetadataVisitorTest
ファイルから) は FragmentMetadataVisitor
を使って MkvElement
オブジェクトからデータを取得する方法を示しています。
FragmentMetadataVisitor fragmentVisitor = FragmentMetadataVisitor.create(); StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(new InputStreamParserByteSource(in)); int segmentCount = 0; while(mkvStreamReader.mightHaveNext()) { Optional<MkvElement> mkvElement = mkvStreamReader.nextIfAvailable(); if (mkvElement.isPresent()) { mkvElement.get().accept(fragmentVisitor); if (MkvTypeInfos.SIMPLEBLOCK.equals(mkvElement.get().getElementMetaData().getTypeInfo())) { MkvDataElement dataElement = (MkvDataElement) mkvElement.get(); Frame frame = ((MkvValue<Frame>)dataElement.getValueCopy()).getVal(); MkvTrackMetadata trackMetadata = fragmentVisitor.getMkvTrackMetadata(frame.getTrackNumber()); assertTrackAndFragmentInfo(fragmentVisitor, frame, trackMetadata); } if (MkvTypeInfos.SEGMENT.equals(mkvElement.get().getElementMetaData().getTypeInfo())) { if (mkvElement.get() instanceof MkvEndMasterElement) { if (segmentCount < continuationTokens.size()) { Optional<String> continuationToken = fragmentVisitor.getContinuationToken(); Assert.assertTrue(continuationToken.isPresent()); Assert.assertEquals(continuationTokens.get(segmentCount), continuationToken.get()); } segmentCount++; } } } }
前述の例は、次のコーディングパターンを示しています。
-
データ解析のための
FragmentMetadataVisitor
およびデータ提供のための StreamingMkvReader を作成します。 -
ストリーム内の各
MkvElement
について、そのメタデータがSIMPLEBLOCK
タイプかどうかを検証します。 -
該当する場合は
MkvElement
からMkvDataElement
を取得します。 -
MkvDataElement
からFrame
(メディアデータ) を取得します。 -
FragmentMetadataVisitor
からFrame
用のMkvTrackMetadata
を取得します。 -
Frame
およびMkvTrackMetadata
オブジェクトから次のデータを取得して検証します。-
追跡番号。
-
フレームのピクセルの高さ。
-
フレームのピクセルの幅。
-
フレームのエンコードに使用するコーデックのコーデック ID。
-
このフレームが順番に到着したこと。前のフレームのトラック番号が存在する場合、現在のフレームのトラック番号より小さいことを確認します。
-
プロジェクトで FragmentMetadataVisitor
を使用するには、ビジターの accept
方法を使って MkvElement
オブジェクトをビジターにパスします。
mkvElement.get().accept(fragmentVisitor);
OutputSegmentMerger
このクラスは、ストリーム内の異なるトラックのメタデータを単一のセグメントを持つストリームにマージします。
次のコード例 (FragmentMetadataVisitorTest
ファイルから) は、OutputSegmentMerger
を使って inputBytes
と呼ばれるバイト配列の追跡メタデータをマージする方法を示しています。
FragmentMetadataVisitor fragmentVisitor = FragmentMetadataVisitor.create(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); OutputSegmentMerger outputSegmentMerger = OutputSegmentMerger.createDefault(outputStream); CompositeMkvElementVisitor compositeVisitor = new TestCompositeVisitor(fragmentVisitor, outputSegmentMerger); final InputStream in = TestResourceUtil.getTestInputStream("output_get_media.mkv"); StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(new InputStreamParserByteSource(in)); while (mkvStreamReader.mightHaveNext()) { Optional<MkvElement> mkvElement = mkvStreamReader.nextIfAvailable(); if (mkvElement.isPresent()) { mkvElement.get().accept(compositeVisitor); if (MkvTypeInfos.SIMPLEBLOCK.equals(mkvElement.get().getElementMetaData().getTypeInfo())) { MkvDataElement dataElement = (MkvDataElement) mkvElement.get(); Frame frame = ((MkvValue<Frame>) dataElement.getValueCopy()).getVal(); Assert.assertTrue(frame.getFrameData().limit() > 0); MkvTrackMetadata trackMetadata = fragmentVisitor.getMkvTrackMetadata(frame.getTrackNumber()); assertTrackAndFragmentInfo(fragmentVisitor, frame, trackMetadata); } }
前述の例は、次のコーディングパターンを示しています。
-
FragmentMetadataVisitor を作成してストリームからメタデータを取得する。
-
出力ストリームを作成してマージされたメタデータを取得する。
-
OutputSegmentMerger
を作成し、ByteArrayOutputStream
に渡す。 -
2 つのビジターを含む
CompositeMkvElementVisitor
を作成する。 -
指定されたファイルを指す
InputStream
を作成する。 -
入力データ内の各要素を出力ストリームにマージします。
KinesisVideoExample
これは、Kinesis ビデオストリームパーサーライブラリの使用方法を示すサンプルアプリケーションです。
このクラスは次の操作を実行します。
-
Kinesis のビデオストリームを作成します。指定した名前がすでに存在する場合は、ストリームが削除され、再作成されます。
-
Kinesis ビデオストリームPutMediaにビデオフラグメントをストリーミングするための呼び出し。
-
Kinesis ビデオストリームからビデオフラグメントをストリーミングGetMediaするための呼び出し。
-
StreamingMkvReader を使用してストリームで返されたフラグメントを解析し、FragmentMetadataVisitor を使用してフラグメントを記録します。
ストリームを削除して再作成
次のコード例 (StreamOps.java
ファイルから) は、特定の Kinesis のビデオストリーム を削除します。
//Delete the stream amazonKinesisVideo.deleteStream(new DeleteStreamRequest().withStreamARN(streamInfo.get().getStreamARN()));
次のコード例 (StreamOps.java
ファイルから) は、指定された名前の Kinesis のビデオストリームを作成します。
amazonKinesisVideo.createStream(new CreateStreamRequest().withStreamName(streamName) .withDataRetentionInHours(DATA_RETENTION_IN_HOURS) .withMediaType("video/h264"));
呼び出し PutMedia
次のコード例 ( PutMediaWorker.java
ファイルから) は、ストリームPutMediaで を呼び出します。
putMedia.putMedia(new PutMediaRequest().withStreamName(streamName) .withFragmentTimecodeType(FragmentTimecodeType.RELATIVE) .withProducerStartTimestamp(new Date()) .withPayload(inputStream), new PutMediaAckResponseHandler() { ... });
呼び出し GetMedia
次のコード例 ( GetMediaWorker.java
ファイルから) は、ストリームGetMediaで を呼び出します。
GetMediaResult result = videoMedia.getMedia(new GetMediaRequest().withStreamName(streamName).withStartSelector(startSelector));
GetMedia 結果を解析する
このセクションでは、StreamingMkvReader、FragmentMetadataVisitor、CompositeMkvElementVisitor
を使用して、GetMedia
から返されたデータを解析し、ファイルに保存して、ログに記録する方法について説明します。
GetMedia で の出力を読み取る StreamingMkvReader
次のコード例 ( GetMediaWorker.java
ファイルから) は StreamingMkvReaderを作成し、それを使用して GetMediaオペレーションの結果を解析します。
StreamingMkvReader mkvStreamReader = StreamingMkvReader.createDefault(new InputStreamParserByteSource(result.getPayload())); log.info("StreamingMkvReader created for stream {} ", streamName); try { mkvStreamReader.apply(this.elementVisitor); } catch (MkvElementVisitException e) { log.error("Exception while accepting visitor {}", e); }
上記のコード例では、StreamingMkvReader は GetMedia
結果のペイロードから MKVElement
オブジェクトを取得します。次のセクションでは、要素は FragmentMetadataVisitor に渡されます。
を使用してフラグメントを取得する FragmentMetadataVisitor
次のコード例 (KinesisVideoExample.java
および StreamingMkvReader.java
ファイルから) は、FragmentMetadataVisitor を作成します。StreamingMkvReader で反復された MkvElement
オブジェクトは、accept
メソッドを使用して訪問者に渡されます。
KinesisVideoExample.java
: から
FragmentMetadataVisitor fragmentMetadataVisitor = FragmentMetadataVisitor.create();
StreamingMkvReader.java
: から
if (mkvElementOptional.isPresent()) { //Apply the MkvElement to the visitor mkvElementOptional.get().accept(elementVisitor); }
要素を記録し、ファイルに書き込む
次のコード例 (KinesisVideoExample.java
ファイルから) は、以下のオブジェクトを作成し、それらを GetMediaProcessingArguments
関数の戻り値の一部として返します。
-
システムログに書き込む
LogVisitor
(MkvElementVisitor
の拡張)。 -
受信データを MKVファイルに書き
OutputStream
込む 。 -
OutputStream
にバインドされたデータをバッファするBufferedOutputStream
。 -
GetMedia
結果内の連続した要素を同じトラックとEBMLデータにマージOutputSegmentMergerする 。 -
FragmentMetadataVisitor、OutputSegmentMerger、および を単一の要素訪問者
LogVisitor
に構成CompositeMkvElementVisitor
する 。
//A visitor used to log as the GetMedia stream is processed. LogVisitor logVisitor = new LogVisitor(fragmentMetadataVisitor); //An OutputSegmentMerger to combine multiple segments that share track and ebml metadata into one //mkv segment. OutputStream fileOutputStream = Files.newOutputStream(Paths.get("kinesis_video_example_merged_output2.mkv"), StandardOpenOption.WRITE, StandardOpenOption.CREATE); BufferedOutputStream outputStream = new BufferedOutputStream(fileOutputStream); OutputSegmentMerger outputSegmentMerger = OutputSegmentMerger.createDefault(outputStream); //A composite visitor to encapsulate the three visitors. CompositeMkvElementVisitor mkvElementVisitor = new CompositeMkvElementVisitor(fragmentMetadataVisitor, outputSegmentMerger, logVisitor); return new GetMediaProcessingArguments(outputStream, logVisitor, mkvElementVisitor);
その後、メディア処理引数は に渡されGetMediaWorker
、次に に渡されExecutorService
、別のスレッドでワーカーを実行します。
GetMediaWorker getMediaWorker = GetMediaWorker.create(getRegion(), getCredentialsProvider(), getStreamName(), new StartSelector().withStartSelectorType(StartSelectorType.EARLIEST), amazonKinesisVideo, getMediaProcessingArgumentsLocal.getMkvElementVisitor()); executorService.submit(getMediaWorker);