From 2d8544e43e10ef91a719a7c4ab70a79bd7bc277e Mon Sep 17 00:00:00 2001 From: Raul Vecchione Date: Fri, 27 Jul 2018 11:07:08 -0600 Subject: [PATCH 1/5] New Encoding Example: CreateHLSEncodingWithAES128.java --- .../bitmovin/api/examples/CreateHLSEncodingWithAES128.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java diff --git a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java new file mode 100644 index 0000000..2246ad5 --- /dev/null +++ b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java @@ -0,0 +1,4 @@ +package com.bitmovin.api.examples; + +public class CreateHLSEncodingWithAES128 { +} From b5b1af24a9f9e343a6f8e4b159de4be1e17f2c00 Mon Sep 17 00:00:00 2001 From: Raul Vecchione Date: Fri, 27 Jul 2018 11:13:19 -0600 Subject: [PATCH 2/5] Added File CreateHLSEncodingWithAES128.java --- .../examples/CreateHLSEncodingWithAES128.java | 237 +++++++++++++++++- 1 file changed, 236 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java index 2246ad5..d791ae8 100644 --- a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java +++ b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java @@ -1,4 +1,239 @@ package com.bitmovin.api.examples; -public class CreateHLSEncodingWithAES128 { +import com.bitmovin.api.BitmovinApi; +import com.bitmovin.api.encoding.AclEntry; +import com.bitmovin.api.encoding.AclPermission; +import com.bitmovin.api.encoding.EncodingOutput; +import com.bitmovin.api.encoding.InputStream; +import com.bitmovin.api.encoding.codecConfigurations.AACAudioConfig; +import com.bitmovin.api.encoding.codecConfigurations.H264VideoConfiguration; +import com.bitmovin.api.encoding.codecConfigurations.enums.ProfileH264; +import com.bitmovin.api.encoding.encodings.Encoding; +import com.bitmovin.api.encoding.encodings.drms.AesEncryptionDrm; +import com.bitmovin.api.encoding.encodings.drms.enums.AESEncryptionMethod; +import com.bitmovin.api.encoding.encodings.muxing.MuxingStream; +import com.bitmovin.api.encoding.encodings.muxing.TSMuxing; +import com.bitmovin.api.encoding.encodings.streams.Stream; +import com.bitmovin.api.encoding.enums.CloudRegion; +import com.bitmovin.api.encoding.enums.StreamSelectionMode; +import com.bitmovin.api.encoding.inputs.HttpsInput; +import com.bitmovin.api.encoding.manifest.hls.HlsManifest; +import com.bitmovin.api.encoding.manifest.hls.StreamInfo; +import com.bitmovin.api.encoding.outputs.Output; +import com.bitmovin.api.encoding.outputs.S3Output; +import com.bitmovin.api.encoding.status.Task; +import com.bitmovin.api.enums.Status; +import com.bitmovin.api.examples.util.H264Representation; +import com.bitmovin.api.exceptions.BitmovinApiException; +import com.bitmovin.api.http.RestException; +import com.mashape.unirest.http.exceptions.UnirestException; +import org.junit.Assert; +import org.junit.Test; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.*; + +/** + * Created by Raul Vecchione on 26.07.18. + */ +public class CreateHLSEncodingWithAES128 +{ + private static String API_KEY = ""; + + private static CloudRegion cloudRegion = CloudRegion.AWS_US_WEST_1; + + private static String HTTPS_INPUT_HOST = ""; // ex.: storage.googleapis.com/ + private static String HTTPS_INPUT_PATH = ""; // ex.: bitmovin-api-us-west1-ci-input/path/myfile.mp4 + private static String S3_OUTPUT_ACCESSKEY = ""; + private static String S3_OUTPUT_SECRET_KEY = ""; + private static String S3_OUTPUT_BUCKET_NAME = "BUCKET_NAME"; + private static String OUTPUT_BASE_PATH = "path/to/your/outputs/" + new Date().getTime(); + + private static BitmovinApi bitmovinApi; + + @Test + public void testEncoding() throws IOException, BitmovinApiException, UnirestException, URISyntaxException, RestException, InterruptedException + { + bitmovinApi = new BitmovinApi(API_KEY); + Encoding encoding = new Encoding(); + encoding.setName("JAVA Encoding HLS With AES-128"); + encoding.setCloudRegion(cloudRegion); + encoding = bitmovinApi.encoding.create(encoding); + + HttpsInput input = new HttpsInput(); + input.setHost(HTTPS_INPUT_HOST); + input = bitmovinApi.input.https.create(input); + + S3Output output = new S3Output(); + output.setAccessKey(S3_OUTPUT_ACCESSKEY); + output.setSecretKey(S3_OUTPUT_SECRET_KEY); + output.setBucketName(S3_OUTPUT_BUCKET_NAME); + output = bitmovinApi.output.s3.create(output); + + // Encoding Configuration - Adding h264 Representations + List h264Representations = new ArrayList<>(); + h264Representations.add ( new H264Representation(null, 240, null, 400L, ProfileH264.HIGH)); + h264Representations.add(new H264Representation(null, 360, null, 800L, ProfileH264.HIGH)); + h264Representations.add(new H264Representation(null, 480, null, 1200L, ProfileH264.HIGH)); + h264Representations.add(new H264Representation(null, 720, null, 2400L, ProfileH264.HIGH)); + h264Representations.add(new H264Representation(null, 1080, null, 4800L, ProfileH264.HIGH)); + + // Encoding Configuration - Audio + AACAudioConfig aacConfiguration = new AACAudioConfig(); + aacConfiguration.setBitrate(128000L); + aacConfiguration.setRate(48000f); + aacConfiguration = bitmovinApi.configuration.audioAAC.create(aacConfiguration); + + for (H264Representation representation : h264Representations) { + H264VideoConfiguration videoConfiguration = new H264VideoConfiguration(); + videoConfiguration.setHeight(representation.getHeight()); + videoConfiguration.setBitrate(representation.getBitrate()*1000); + videoConfiguration.setProfile(ProfileH264.HIGH); + videoConfiguration = bitmovinApi.configuration.videoH264.create(videoConfiguration); + representation.setConfiguration(videoConfiguration); + + // Encoding Configuration - Streams + InputStream inputStreamAudio = new InputStream(); + inputStreamAudio.setInputPath(HTTPS_INPUT_PATH); + inputStreamAudio.setInputId(input.getId()); + inputStreamAudio.setSelectionMode(StreamSelectionMode.AUTO); + inputStreamAudio.setPosition(0); + + InputStream inputStreamVideo = new InputStream(); + inputStreamVideo.setInputPath(HTTPS_INPUT_PATH); + inputStreamVideo.setInputId(input.getId()); + inputStreamVideo.setSelectionMode(StreamSelectionMode.AUTO); + inputStreamVideo.setPosition(0); + + Stream audioStream = new Stream(); + audioStream.setCodecConfigId(aacConfiguration.getId()); + audioStream.setInputStreams(Collections.singleton(inputStreamAudio)); + audioStream = bitmovinApi.encoding.stream.addStream(encoding, audioStream); + representation.setStream(audioStream); + + Stream videoStream = new Stream(); + videoStream.setCodecConfigId(videoConfiguration.getId()); + videoStream.setInputStreams(Collections.singleton(inputStreamVideo)); + videoStream = bitmovinApi.encoding.stream.addStream(encoding, videoStream); + representation.setStream(videoStream); + + // AES - Configuration + AesEncryptionDrm aesEncryptionDrm = new AesEncryptionDrm(); + aesEncryptionDrm.setKey(""); // 128 bit (16 bytes) ex.: cab5b529ae28d5cc5e3e7bc3fd4a544d + aesEncryptionDrm.setIv(""); // 128 bit (16 bytes) ex.: 08eecef4b026deec395234d94218273d + aesEncryptionDrm.setId("DRM_AES_128" + String.format("%sp_%s", representation.getHeight(), representation.getBitrate())); + aesEncryptionDrm.setMethod(AESEncryptionMethod.AES_128); + + // Muxing Configuration - Creating Muxing configuration + TSMuxing tsMuxing = this.createTSMuxingNoOutput(encoding, Arrays.asList( videoStream, audioStream)); + System.out.println("Output path: " + OUTPUT_BASE_PATH + "/video/hls/drm/" + String.format("%sp_%s", representation.getHeight(), representation.getBitrate())); + this.addOutputToDRM(aesEncryptionDrm, output, OUTPUT_BASE_PATH + "/video/hls/drm/" + String.format("%sp_%s", representation.getHeight(), representation.getBitrate()), tsMuxing); + this.addAesDrmToTssMuxing(encoding, tsMuxing, aesEncryptionDrm); + representation.setTsMuxing(tsMuxing); + } + + // Start Encoding + this.bitmovinApi.encoding.start(encoding); + + Task status = bitmovinApi.encoding.getStatus(encoding); + while (status.getStatus() != Status.FINISHED && status.getStatus() != Status.ERROR) + { + status = bitmovinApi.encoding.getStatus(encoding); + Thread.sleep(2500); + } + + System.out.println(String.format("Encoding finished with status %s", status.getStatus().toString())); + + Assert.assertEquals(Status.FINISHED, status.getStatus()); + EncodingOutput manifestOutput = new EncodingOutput(); + manifestOutput.setOutputId(output.getId()); + manifestOutput.setOutputPath(OUTPUT_BASE_PATH); + manifestOutput.setAcl(new ArrayList() + {{ + this.add(new AclEntry(AclPermission.PUBLIC_READ)); + }}); + + // Create HLS Manifest + HlsManifest hlsManifest = new HlsManifest(); + hlsManifest.setName("stream.m3u8"); + hlsManifest.setOutputs(Collections.singletonList(manifestOutput)); + hlsManifest = bitmovinApi.manifest.hls.create(hlsManifest); + + for (H264Representation representation : h264Representations) + { + this.addStreamInfo(String.format("video_%sp_%s.m3u8", representation.getHeight(), representation.getBitrate()), + encoding.getId(), representation.getStream().getId(), representation.getTsMuxing().getId(), + String.format("video/hls/drm/%sp_%s/", representation.getHeight(), representation.getBitrate()), + hlsManifest, representation.getTsMuxing().getDrmConfigs().get(0).getId()); + } + + bitmovinApi.manifest.hls.startGeneration(hlsManifest); + Status hlsStatus = bitmovinApi.manifest.hls.getGenerationStatus(hlsManifest); + while (hlsStatus != Status.FINISHED && hlsStatus != Status.ERROR) + { + hlsStatus = bitmovinApi.manifest.hls.getGenerationStatus(hlsManifest); + Thread.sleep(2500); + } + System.out.println(String.format("HLS Manifest generation finished with status %s", hlsStatus.toString())); + Assert.assertEquals(Status.FINISHED, hlsStatus); + + } + + private void addStreamInfo(String uri, String encodingId, String streamId, String muxingId, String segmentPath, HlsManifest manifest, String aesEncryptionDrmId) + throws URISyntaxException, BitmovinApiException, RestException, UnirestException, IOException + { + StreamInfo s = new StreamInfo(); + s.setUri(uri); + s.setEncodingId(encodingId); + s.setStreamId(streamId); + s.setMuxingId(muxingId); + s.setSegmentPath(segmentPath); + s.setDrmId(aesEncryptionDrmId); + bitmovinApi.manifest.hls.createStreamInfo(manifest, s); + } + + private TSMuxing createTSMuxingNoOutput(Encoding encoding, List streams) + throws URISyntaxException, BitmovinApiException, RestException, UnirestException, IOException + { + TSMuxing muxing = new TSMuxing(); + MuxingStream list = new MuxingStream(); + List muxingStreams = new ArrayList<>(); + for (Stream stream : streams) + { + MuxingStream muxingStreamVideo = new MuxingStream(); + muxingStreamVideo.setStreamId(stream.getId()); + muxingStreams.add(muxingStreamVideo); + } + muxing.setStreams(muxingStreams); + muxing.setSegmentLength(4.0); + muxing = bitmovinApi.encoding.muxing.addTSMuxingToEncoding(encoding, muxing); + return muxing; + } + + private void addOutputToDRM(AesEncryptionDrm aesEncryptionDrm, Output output, String outputPath, TSMuxing tsMuxing) + { + List drmOutputs = aesEncryptionDrm.getOutputs(); + + if (drmOutputs == null) + { + drmOutputs = new ArrayList<>(); + aesEncryptionDrm.setOutputs(drmOutputs); + } + + EncodingOutput drmOutput = new EncodingOutput(); + drmOutput.setOutputId(output.getId()); + drmOutput.setOutputPath(outputPath); + drmOutputs.add(drmOutput); + tsMuxing.setOutputs(Collections.singletonList(drmOutput)); + } + + private AesEncryptionDrm addAesDrmToTssMuxing(Encoding encoding, TSMuxing tsMuxing, AesEncryptionDrm aesEncryptionDrm) + throws BitmovinApiException, IOException, RestException, UnirestException, URISyntaxException + { + AesEncryptionDrm result = bitmovinApi.encoding.muxing.addAESEncryptionToTssMuxing(encoding, tsMuxing, aesEncryptionDrm); + Assert.assertNotNull(result.getId()); + tsMuxing.getDrmConfigs().add(result); + return result; + } } From de3a5eac78cf9bfebb044e895fd2547f0d838bde Mon Sep 17 00:00:00 2001 From: Raul Vecchione Date: Tue, 31 Jul 2018 11:21:13 -0600 Subject: [PATCH 3/5] Sets AES-128 Keys and IV in static at the top --- .../bitmovin/api/examples/CreateHLSEncodingWithAES128.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java index d791ae8..82c5d5e 100644 --- a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java +++ b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java @@ -49,6 +49,8 @@ public class CreateHLSEncodingWithAES128 private static String S3_OUTPUT_SECRET_KEY = ""; private static String S3_OUTPUT_BUCKET_NAME = "BUCKET_NAME"; private static String OUTPUT_BASE_PATH = "path/to/your/outputs/" + new Date().getTime(); + private static String AES_STRING_KEY = "" ; // 128 bit (16 bytes) ex.: cab5b529ae28d5cc5e3e7bc3fd4a544d + private static String AES_STRING_IV = "" ; // 128 bit (16 bytes) ex.: 08eecef4b026deec395234d94218273d private static BitmovinApi bitmovinApi; @@ -120,8 +122,8 @@ public void testEncoding() throws IOException, BitmovinApiException, UnirestExce // AES - Configuration AesEncryptionDrm aesEncryptionDrm = new AesEncryptionDrm(); - aesEncryptionDrm.setKey(""); // 128 bit (16 bytes) ex.: cab5b529ae28d5cc5e3e7bc3fd4a544d - aesEncryptionDrm.setIv(""); // 128 bit (16 bytes) ex.: 08eecef4b026deec395234d94218273d + aesEncryptionDrm.setKey(AES_STRING_KEY); + aesEncryptionDrm.setIv(AES_STRING_IV); aesEncryptionDrm.setId("DRM_AES_128" + String.format("%sp_%s", representation.getHeight(), representation.getBitrate())); aesEncryptionDrm.setMethod(AESEncryptionMethod.AES_128); From 3540c6ed2f85a8d5bbd3ec60c3bcd70dbc90fbdd Mon Sep 17 00:00:00 2001 From: Raul Vecchione Date: Tue, 31 Jul 2018 13:53:13 -0600 Subject: [PATCH 4/5] Clean up after Gfronza review --- .../bitmovin/api/examples/CreateHLSEncodingWithAES128.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java index 82c5d5e..aca116d 100644 --- a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java +++ b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java @@ -75,7 +75,7 @@ public void testEncoding() throws IOException, BitmovinApiException, UnirestExce // Encoding Configuration - Adding h264 Representations List h264Representations = new ArrayList<>(); - h264Representations.add ( new H264Representation(null, 240, null, 400L, ProfileH264.HIGH)); + h264Representations.add (new H264Representation(null, 240, null, 400L, ProfileH264.HIGH)); h264Representations.add(new H264Representation(null, 360, null, 800L, ProfileH264.HIGH)); h264Representations.add(new H264Representation(null, 480, null, 1200L, ProfileH264.HIGH)); h264Representations.add(new H264Representation(null, 720, null, 2400L, ProfileH264.HIGH)); @@ -87,7 +87,8 @@ public void testEncoding() throws IOException, BitmovinApiException, UnirestExce aacConfiguration.setRate(48000f); aacConfiguration = bitmovinApi.configuration.audioAAC.create(aacConfiguration); - for (H264Representation representation : h264Representations) { + for (H264Representation representation : h264Representations) + { H264VideoConfiguration videoConfiguration = new H264VideoConfiguration(); videoConfiguration.setHeight(representation.getHeight()); videoConfiguration.setBitrate(representation.getBitrate()*1000); From 1e832614fdc0cb68b95019a50076afcdf8dc14ff Mon Sep 17 00:00:00 2001 From: Raul Vecchione Date: Mon, 6 Aug 2018 11:00:18 -0600 Subject: [PATCH 5/5] Update HLS AES128 example. Modify audio representation. --- .../examples/CreateHLSEncodingWithAES128.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java index aca116d..3fcbb43 100644 --- a/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java +++ b/src/test/java/com/bitmovin/api/examples/CreateHLSEncodingWithAES128.java @@ -87,6 +87,18 @@ public void testEncoding() throws IOException, BitmovinApiException, UnirestExce aacConfiguration.setRate(48000f); aacConfiguration = bitmovinApi.configuration.audioAAC.create(aacConfiguration); + InputStream inputStreamAudio = new InputStream(); + inputStreamAudio.setInputPath(HTTPS_INPUT_PATH); + inputStreamAudio.setInputId(input.getId()); + inputStreamAudio.setSelectionMode(StreamSelectionMode.AUTO); + inputStreamAudio.setPosition(0); + + Stream audioStream = new Stream(); + audioStream.setCodecConfigId(aacConfiguration.getId()); + audioStream.setInputStreams(Collections.singleton(inputStreamAudio)); + audioStream = bitmovinApi.encoding.stream.addStream(encoding, audioStream); + h264Representations.get(0).setStream(audioStream); + for (H264Representation representation : h264Representations) { H264VideoConfiguration videoConfiguration = new H264VideoConfiguration(); @@ -97,24 +109,12 @@ public void testEncoding() throws IOException, BitmovinApiException, UnirestExce representation.setConfiguration(videoConfiguration); // Encoding Configuration - Streams - InputStream inputStreamAudio = new InputStream(); - inputStreamAudio.setInputPath(HTTPS_INPUT_PATH); - inputStreamAudio.setInputId(input.getId()); - inputStreamAudio.setSelectionMode(StreamSelectionMode.AUTO); - inputStreamAudio.setPosition(0); - InputStream inputStreamVideo = new InputStream(); inputStreamVideo.setInputPath(HTTPS_INPUT_PATH); inputStreamVideo.setInputId(input.getId()); inputStreamVideo.setSelectionMode(StreamSelectionMode.AUTO); inputStreamVideo.setPosition(0); - Stream audioStream = new Stream(); - audioStream.setCodecConfigId(aacConfiguration.getId()); - audioStream.setInputStreams(Collections.singleton(inputStreamAudio)); - audioStream = bitmovinApi.encoding.stream.addStream(encoding, audioStream); - representation.setStream(audioStream); - Stream videoStream = new Stream(); videoStream.setCodecConfigId(videoConfiguration.getId()); videoStream.setInputStreams(Collections.singleton(inputStreamVideo));