Media Flow

Oracle Cloud Infrastructure(OCI) Media Flow는 개발자가 비디오 및 오디오 미디어를 온디맨드 스트리밍을 위한 다양한 형식으로 프로세싱하고, API 및 명령줄 인터페이스(CLI) 도구를 통해 일괄처리 작업을 실행할 수 있는 서비스입니다. OCI Media Flow를 사용하면 메타데이터를 보강하여 콘텐츠 관리 시스템(CMS)에서 비디오 콘텐츠를 더 쉽게 검색할 수 있고, AI 도구를 사용하여 비디오 콘텐츠를 제공하며 다국어 자막 지원 등의 다양한 기능을 추가할 수도 있습니다.

Oracle Cloud Infrastructure(OCI) Media Flow: 개요(2:02)

OCI Media Flow 의 작동 방식

OCI Media Flow 의 작동 방식 다이어그램
비디오 파일이 생성되어 Oracle Cloud Infrastructure(OCI) Object Storage에 업로드됩니다. Oracle Cloud Infrastructure(OCI) Media Flow를 통해 비디오 파일로부터 썸네일이 사용자가 설정한 시간 간격으로 생성되고, 생성된 썸네일 또한 OCI Object Storage에 저장할 수 있습니다. 또한 OCI Media Flow는 스트리밍을 위해 단일 비디오 파일의 다양한 변형을 생성하고, HLS 스트리밍을 위한 비디오 매니페스트 파일이 고객의 파일 저장소에 추가됩니다. OCI Media Flow는 검색 가능한 콘텐츠 인덱스가 포함된 AI 메타데이터가 담긴 JSON 파일을 생성합니다. OCI Media Flow는 스트리밍의 전제 조건인 여러 개의 파편화된 MP4 파일들 및 마스터 재생 목록을 생성합니다. OCI Media Streams은 유효한 HLS 마스터 재생 목록을 수집하고 비디오 스트리밍용 비디오 패키지를 생성합니다.

개발자가 비디오 파일을 준비 및 트랜스코딩하는 방법

미디어 플로를 생성하고 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 사용 사례

비디오 저장 및 관리

OCI Media Flow는 비디오를 프로세싱하고 CMS에 저장하기 위한 메타데이터를 제공하고, 비디오를 전송용으로 트랜스코딩하고, 다양한 재생 해상도에 대응하는 여러 버전의 비디오를 생성하고, 스트리밍에 대비한 마스터 재생 목록을 생성합니다.

비디오 클리핑

더 간단히 비디오를 클리핑할 수 있습니다. 원하는 해상도와 구성을 선택하면 OCI Media Flow가 Facebook, Twitter 등 인기 있는 소셜 미디어 사이트에 적합한 비디오 포맷을 자동으로 적용하므로 다양한 시청자들과 간단히 비디오를 공유할 수 있습니다.

학습 플랫폼 생성

OCI Media Flow로 학습 플랫폼 경험을 위한 비디오를 간단히 제작, 처리, 저장할 수 있습니다.

비디오 아카이빙

OCI Media Flow는 아카이브된 비디오 콘텐츠의 처리, 관리, 검색을 간소화하여 검색 효율을 향상시킵니다. OCI Object Storage를 통해 고용량 비디오를 저렴하게 저장할 수 있습니다.

2022년 7월 20일

Oracle, OCI 상에서의 비디오 운영을 가속화하는 OCI Digital Media Services 출시

Oracle, Principal Product Manager, Remi Fourreau

기쁜 마음으로 Oracle Cloud Infrastructure(OCI)용 Digital Media Services(DMS)의 정식 출시를 발표합니다. 비디오 콘텐츠를 보유한 OCI 고객은 DMS Media Flow의 저렴한 미디어 프로세싱 기능을 활용하고, DMS Media Streams 서비스를 통해 비디오를 전송할 수 있습니다. 해당 서비스들이 제공하는, 보다 나은 고객 경험을 창출하고 비즈니스 운영을 개선하기 위한 신규 미디어 기능들을 통해 애플리케이션 및 비즈니스 프로세스를 더욱 강화할 수 있습니다.

게시글 전문 읽어보기

추천 블로그

모두 보기

OCI Media Flow 시작하기

상시 무료 클라우드 서비스를 사용해보고 30일 평가판을 받으세요

Oracle은 Media Flow, Media Streams, AI Services 등의 엄선된 서비스를 시간 제한 없이 무료로 이용할 수 있는 Free Tier와 함께 추가 클라우드 서비스 체험을 지원하기 위한 미화 300 달러 상당의 무료 크레디트를 제공합니다. 자세한 내용을 확인하고 지금 바로 무료 계정에 가입해보세요.

  • Oracle Cloud 무료 체험에는 무엇이 포함되어 있나요?

    • 상시 무료
    • Autonomous Database 2개(각 20GB)
    • 컴퓨팅 VM
    • 100GB 블록 볼륨
    • 10GB의 객체 스토리지

영업 팀에 문의하기

Media Flow에 대한 추가 정보가 필요하신가요? Oracle의 전문가가 도와 드리겠습니다.

  • 다음과 같은 질문에 답해드릴 수 있습니다.

    • OCI Media Flow와 원활히 통합 가능한 서비스로는 어떤 것들이 있나요?
    • 우리 회사의 도입 비용은 어느 정도일까요?
    • Media Flow가 지원하는 다양한 비디오 포맷에는 어떤 것들이 있나요?