Oracle Cloud Infrastructure(OCI) Media Flow는 개발자가 비디오 및 오디오 미디어를 온디맨드 스트리밍을 위한 다양한 형식으로 프로세싱하고, API 및 명령줄 인터페이스(CLI) 도구를 통해 일괄처리 작업을 실행할 수 있는 서비스입니다. OCI Media Flow를 사용하면 메타데이터를 보강하여 콘텐츠 관리 시스템(CMS)에서 비디오 콘텐츠를 더 쉽게 검색할 수 있고, AI 도구를 사용하여 비디오 콘텐츠를 제공하며 다국어 자막 지원 등의 다양한 기능을 추가할 수도 있습니다.
H264, H265, VP8, VP9 등의 전송 포맷과 HLS, MPEG-DASH 등의 패키징 포맷을 선택할 수 있습니다. OCI를 사용하면 인프라를 직접 프로비저닝할 필요가 없으므로 온라인 서버를 신경쓸 필요 없이 비디오 파일을 전송할 수 있으며 패치, 업데이트, 수요 급증에 원활히 대응할 수 있습니다.
비트레이트 최적화, 비디오 내 객체 감지, 자동화된 비디오 편집과 같은 머신러닝 기반 콘텐츠 처리 기능의 이점을 누릴 수 있습니다.
타사와 달리 Oracle은 OCI Media Flow에 직접 통합되어 있고, 동일한 콘솔을 통해 사용할 수 있는 AI 서비스들을 제공합니다.
합리적이고 저렴한 가격으로 이용 가능합니다. 사용량에 비례하는 요금만을 지불하면 됩니다. 인프라를 직접 유지 보수할 필요도 없습니다.
미디어 플로를 생성하고 OCI Media Flow 작업을 실행하는 방법을 살펴보세요. OCI의 최신 Java SDK가 필요하고, 출력 파일의 접두어를 입력해야 합니다. 하단의 예제는 데모 용도로만 사용해야 하고, 실제 운용에 사용해서는 안 됩니다.
/***********
This is a demo program to create media flow and run media flow jobs.
This requires the latest java SDK of OCI.
Takes input of the prefix name for the output files.
This is intended for a demonstration only and not for Production usage.
************/
/***********
1. Accept User Input of prefix for the outputs.
2. Create Media Client.
3. Create Tasks.
4. Create Media Workflow.
5. Create Media Workflow Job.
************/
import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider;
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
import com.oracle.bmc.mediaservices.MediaServicesClient;
import com.oracle.bmc.mediaservices.*;
import com.oracle.bmc.mediaservices.model.MediaWorkflowTask;
import com.oracle.bmc.mediaservices.model.CreateMediaWorkflowDetails;
import com.oracle.bmc.mediaservices.responses.CreateMediaWorkflowResponse;
import com.oracle.bmc.mediaservices.model.MediaWorkflow;
import com.oracle.bmc.mediaservices.requests.*;
import com.oracle.bmc.mediaservices.model.CreateMediaWorkflowJobDetails;
import com.oracle.bmc.mediaservices.model.CreateMediaWorkflowJobByIdDetails;
import com.oracle.bmc.mediaservices.responses.CreateMediaWorkflowJobResponse;
import com.oracle.bmc.mediaservices.model.MediaWorkflowJob;
import org.json.simple.*;
import org.json.simple.parser.*;
import java.util.Collections;
import java.util.*;
import java.util.Scanner;
public class MediaflowDemoApp {
// Get User Input
public static String getUserInput(){
MediaflowDemoApp.printString("Enter a name for the prefix of files:");
Scanner input = new Scanner(System.in);
String prefixInput = input.nextLine();
input.close();
return prefixInput;
}
// Json String to Json Object
public static JSONObject createJSONObject(String jsonString){
JSONObject jsonObject=new JSONObject();
JSONParser jsonParser=new JSONParser();
if ((jsonString != null) && !(jsonString.isEmpty())) {
try {
jsonObject=(JSONObject) jsonParser.parse(jsonString);
} catch (org.json.simple.parser.ParseException e) {
e.printStackTrace();
}
}
return jsonObject;
}
// Print Function
public static void printString(Object stringtoPrint){
System.out.println(stringtoPrint);
}
// Create Media Service Client.
public static MediaServicesClient connectMediaService(){
InstancePrincipalsAuthenticationDetailsProvider provider = InstancePrincipalsAuthenticationDetailsProvider.builder().build();
MediaServicesClient mediaClient = new MediaServicesClient(provider);
// User Principal
// Read config from the profile DEFAULT in the file "~/.oci/config". You can switch to different profile.
// AuthenticationDetailsProvider authenticationDetailsProvider = new ConfigFileAuthenticationDetailsProvider(PROFILE_DEFAULT);
// MediaServicesClient mediaClient = MediaServicesClient.builder().build(authenticationDetailsProvider);
MediaflowDemoApp.printString("Media Client Instantiated");
return mediaClient;
}
// Close Media Service Client
public static void closeMediaService(MediaServicesClient mc){
mc.close();
MediaflowDemoApp.printString("Media Client Closed");
}
// Create Tasks
// Tasks are discrete steps in the workflow.
public static List<MediaWorkflowTask> createTasks(JSONObject arg0,JSONObject arg1,JSONObject arg2,JSONObject arg3,JSONObject arg4){
long version = 1;
List<MediaWorkflowTask> task = new ArrayList<MediaWorkflowTask>();
List<String> typeGetFiles = new ArrayList<String>();
List<String> typeTranscode = new ArrayList<String>();
List<String> typeThumbnail = new ArrayList<String>();
typeGetFiles.add("getFiles");
typeTranscode.add("transcode1");
typeThumbnail.add("thumbnail");
task.add(MediaWorkflowTask.builder().type("getFiles").version(version).key("getFiles").prerequisites(Collections.emptyList()).parameters(arg0).build());
task.add(MediaWorkflowTask.builder().type("transcribe").version(version).key("transcribe").prerequisites(typeGetFiles).parameters(arg4).build());
task.add(MediaWorkflowTask.builder().type("transcode").version(version).key("transcode1").prerequisites(typeGetFiles).parameters(arg1).build());
task.add(MediaWorkflowTask.builder().type("thumbnail").version(version).key("thumbnail").prerequisites(typeTranscode).parameters(arg2).build());
task.add(MediaWorkflowTask.builder().type("putFiles").version(version).key("PutFiles1").prerequisites(typeThumbnail).parameters(arg3).build());
return task;
}
// Create Media Workflow.
public static MediaWorkflow createMediaWorkflow(MediaServicesClient mc, List<MediaWorkflowTask> tasks, JSONObject parameters,String compartment_id){
CreateMediaWorkflowRequest request = CreateMediaWorkflowRequest.builder().createMediaWorkflowDetails(CreateMediaWorkflowDetails.builder().displayName("test-java-sdk").compartmentId(compartment_id).tasks(tasks).parameters(parameters).build()).build();
CreateMediaWorkflowResponse response = mc.createMediaWorkflow(request);
MediaWorkflow mediaflow = response.getMediaWorkflow();
return mediaflow;
}
// Create Media Workflow Job
public static MediaWorkflowJob createWorkflowJob(MediaServicesClient mc, MediaWorkflow mediaflow, String prefixInput, JSONObject parameters, String compartment_id){
String mediaWorkflowId = mediaflow.getId();
CreateMediaWorkflowJobRequest request = CreateMediaWorkflowJobRequest.builder().createMediaWorkflowJobDetails(CreateMediaWorkflowJobByIdDetails.builder().displayName("test-java-sdk-job").compartmentId(compartment_id).mediaWorkflowId(mediaWorkflowId).parameters(parameters).build()).build();
CreateMediaWorkflowJobResponse response = mc.createMediaWorkflowJob(request);
MediaWorkflowJob mediaflowJob = response.getMediaWorkflowJob();
return mediaflowJob;
}
public static void main(String[] args) {
// **Variable Declarations** //
String compartment_id = "ocid1.compartment.oc1..aaaaaaaabhuut4zoztxlfneotrwuauqt5wjhmj4kxaka6ajme4ipxqlcwv6a";
String src_bucket = "test";
String dst_bucket = "test";
String namespace = "test";
String src_video = "test";
String prefix_input = "test";
//* Task Parameters *//
String getobjectParameters = "{\"taskParameters\": [{\"storageType\": \"objectStorage\",\"target\": \"getFiles/${/input/objectName}\",\"namespaceName\": \"${/input/namespaceName}\",\"bucketName\": \"${/input/bucketName}\",\"objectName\": \"${/input/objectName}\"}]}";
String transcodeParameters = "{ \"transcodeType\": \"standardTranscode\", \"standardTranscode\": { \"input\": \"${/getFiles/taskParameters/0/target}\", \"outputPrefix\": \"${/transcode/outputPrefix}\", \"videoCodec\": \"h264\", \"audioCodec\": \"aac\", \"packaging\": { \"packageType\": \"hls\", \"segmentLength\": 6 }, \"ladder\": [ { \"size\": { \"height\": 1080, \"resizeMethod\": \"scale\" } }, { \"size\": { \"height\": 720, \"resizeMethod\": \"scale\" } }, { \"size\": { \"height\": 480, \"resizeMethod\": \"scale\" } }, { \"size\": { \"height\": 360, \"resizeMethod\": \"scale\" } } ] } }";
String thumbnailParameters = "{ \"thumbnails\": { \"input\": \"${/getFiles/taskParameters/0/target}\", \"frameSelectors\": [ { \"namePrefix\": \"thumb\", \"format\": \"jpg\", \"sizes\": [ { \"width\": 390 }, { \"width\": 196 } ], \"clipImagePicker\": { \"percentList\": { \"pickList\": [ 10, 20, 30 ] } } } ] } }";
String finaltaskParameters = "{ \"taskParameters\": [ { \"namespaceName\": \"${/output/namespaceName}\", \"bucketName\": \"${/output/bucketName}\", \"source\": \"${/transcode/outputPrefix}*.m3u8\", \"objectName\": \"${/output/objectNamePath}${/transcode/outputPrefix}\", \"assetCompartmentId\": \"${/output/assetCompartmentId}\", \"registerMetadata\": true }, { \"namespaceName\": \"${/output/namespaceName}\", \"bucketName\": \"${/output/bucketName}\", \"source\": \"master.m3u8\", \"objectName\": \"${/output/objectNamePath}${/transcode/outputPrefix}-master.m3u8\", \"assetCompartmentId\": \"${/output/assetCompartmentId}\", \"registerMetadata\": true }, { \"namespaceName\": \"${/output/namespaceName}\", \"bucketName\": \"${/output/bucketName}\", \"source\": \"*.fmp4\", \"objectName\": \"${/output/objectNamePath}\", \"assetCompartmentId\": \"${/output/assetCompartmentId}\", \"registerMetadata\": true }, { \"namespaceName\": \"${/output/namespaceName}\", \"bucketName\": \"${/output/bucketName}\", \"source\": \"*.${/thumbnail/thumbnails/frameSelectors/0/format}\", \"objectName\": \"${/output/objectNamePath}${/transcode/outputPrefix}-\", \"assetCompartmentId\": \"${/output/assetCompartmentId}\", \"registerMetadata\": true } ] }";
String transcibeParmeters = "{ \"inputVideo\": \"${/getFiles/taskParameters/0/target}\", \"outputAudio\": \"${/output/objectNamePath}${/transcode/outputPrefix}.wav\", \"outputBucketName\": \"${/output/bucketName}\", \"outputNamespaceName\": \"${/output/namespaceName}\", \"outputTranscriptionPrefix\": \"${/output/objectNamePath}${/transcode/outputPrefix}\", \"transcriptionJobCompartment\": \"${/output/assetCompartmentId}\", \"waitForCompletion\" : true }";
String mediaworkflowParameters = "{ \"input\": { \"objectName\": \"${/video/srcVideo}\", \"bucketName\": \"${/video/srcBucket}\", \"namespaceName\": \"${/video/namespace}\" }, \"output\": { \"bucketName\": \"${/video/dstBucket}\", \"namespaceName\": \"${/video/namespace}\", \"assetCompartmentId\": \"${/video/compartmentID}\", \"objectNamePath\": \"sdk_test/${/input/objectName}/\" }, \"transcode\": { \"outputPrefix\": \"${/video/outputPrefixName}\" } }";
String mediaflowjobParameters = "{ \"video\": { \"srcBucket\": \"" + src_bucket+ "\", \"dstBucket\": \"" +dst_bucket+ "\", \"namespace\": \"" +namespace+ "\", \"compartmentID\": \""+compartment_id+"\", \"srcVideo\": \""+src_video+"\", \"outputPrefixName\" : \""+prefix_input+"\" } }";
//* Json Objects of the task parameters *//
JSONObject getobjectParametersJson = MediaflowDemoApp.createJSONObject(getobjectParameters);
JSONObject transcodeParametersJson = MediaflowDemoApp.createJSONObject(transcodeParameters);
JSONObject thumbnailParametersJson = MediaflowDemoApp.createJSONObject(thumbnailParameters);
JSONObject finaltaskParametersJson = MediaflowDemoApp.createJSONObject(finaltaskParameters);
JSONObject transcibeParmetersJson = MediaflowDemoApp.createJSONObject(transcibeParmeters);
JSONObject mediaworkflowParametersJson = MediaflowDemoApp.createJSONObject(mediaworkflowParameters);
JSONObject mediaflowjobParametersJson = MediaflowDemoApp.createJSONObject(mediaflowjobParameters);
/* Debug JSON Prints
MediaflowDemoApp.printString(getobjectParametersJson);
MediaflowDemoApp.printString(transcodeParametersJson);
MediaflowDemoApp.printString(thumbnailParametersJson);
MediaflowDemoApp.printString(finaltaskParametersJson);
MediaflowDemoApp.printString(transcibeParmetersJson);
MediaflowDemoApp.printString(mediaworkflowParametersJson);
MediaflowDemoApp.printString(mediaflowjobParametersJson);*/
// Get User Input
String prefixInput = MediaflowDemoApp.getUserInput();
// Create the tasks for mediaflow
List<MediaWorkflowTask> tasks = MediaflowDemoApp.createTasks(getobjectParametersJson,transcodeParametersJson,thumbnailParametersJson,finaltaskParametersJson,transcibeParmetersJson);
// Connect to media services
MediaServicesClient mediaClient = MediaflowDemoApp.connectMediaService();
// Create MediaWorkFlow
MediaWorkflow mediaflow = MediaflowDemoApp.createMediaWorkflow(mediaClient, tasks, mediaworkflowParametersJson, compartment_id);
// Prints MediaWorkflow OCID
MediaflowDemoApp.printString(mediaflow.getId());
// Create the Workflow Job
MediaWorkflowJob mediaflowJob = MediaflowDemoApp.createWorkflowJob(mediaClient, mediaflow, prefixInput, mediaflowjobParametersJson, compartment_id);
// Print Workflow Job ID
MediaflowDemoApp.printString(mediaflowJob.getId());
// Finally Close the Media Client
MediaflowDemoApp.closeMediaService(mediaClient);
}
}
OCI Media Flow는 비디오를 프로세싱하고 CMS에 저장하기 위한 메타데이터를 제공하고, 비디오를 전송용으로 트랜스코딩하고, 다양한 재생 해상도에 대응하는 여러 버전의 비디오를 생성하고, 스트리밍에 대비한 마스터 재생 목록을 생성합니다.
더 간단히 비디오를 클리핑할 수 있습니다. 원하는 해상도와 구성을 선택하면 OCI Media Flow가 Facebook, Twitter 등 인기 있는 소셜 미디어 사이트에 적합한 비디오 포맷을 자동으로 적용하므로 다양한 시청자들과 간단히 비디오를 공유할 수 있습니다.
OCI Media Flow로 학습 플랫폼 경험을 위한 비디오를 간단히 제작, 처리, 저장할 수 있습니다.
OCI Media Flow는 아카이브된 비디오 콘텐츠의 처리, 관리, 검색을 간소화하여 검색 효율을 향상시킵니다. OCI Object Storage를 통해 고용량 비디오를 저렴하게 저장할 수 있습니다.
Oracle, Principal Product Manager, Remi Fourreau
기쁜 마음으로 Oracle Cloud Infrastructure(OCI)용 Digital Media Services(DMS)의 정식 출시를 발표합니다. 비디오 콘텐츠를 보유한 OCI 고객은 DMS Media Flow의 저렴한 미디어 프로세싱 기능을 활용하고, DMS Media Streams 서비스를 통해 비디오를 전송할 수 있습니다. 해당 서비스들이 제공하는, 보다 나은 고객 경험을 창출하고 비즈니스 운영을 개선하기 위한 신규 미디어 기능들을 통해 애플리케이션 및 비즈니스 프로세스를 더욱 강화할 수 있습니다.
게시글 전문 읽어보기Oracle은 Media Flow, Media Streams, AI Services 등의 엄선된 서비스를 시간 제한 없이 무료로 이용할 수 있는 Free Tier와 함께 추가 클라우드 서비스 체험을 지원하기 위한 미화 300 달러 상당의 무료 크레디트를 제공합니다. 자세한 내용을 확인하고 지금 바로 무료 계정에 가입해보세요.