Media Streams

Oracle Cloud Infrastructure (OCI) Media Streams 服务帮助开发人员打包视频内容,然后从 OCI 或通过内容分发网络 (CDN) 进行流传输。此服务对媒体内容进行加密,以便安全地将其传送到智能电视、移动设备、计算机和游戏机等设备。开发人员现在可以利用 OCI 的可扩展性来提供完整的视频体验,而无需管理基础设施。

Oracle Cloud Infrastructure Media Streams:概览 (1:31)

OCI Media Streams 的工作原理

OCI Media Streams 的工作原理图
创建视频并将其上传到 Oracle Cloud Infrastructure Object Storage。通过 Oracle Cloud Infrastructure Media Flow,可在可配置的时间间隔内创建视频缩略图,并将其存储在 OCI Object Storage 中。OCI Media Flow 还可创建用于流媒体的多种视频变体,并将用于 HLS 流媒体的视频清单文件添加到客户的文件库中。OCI Media Flow 可创建一个带有 AI 元数据的 JSON 文件,其中包含一个可搜索的内容索引。OCI Media Flow 可创建多个分段的 MP4 和主播放列表,这些是流处理的先决条件。OCI Media Streams 接收有效的 HLS 主播放列表,并为视频流创建视频包。

开发人员如何准备视频文件并进行转码

查看如何流式传输媒体和运行 OCI Media Streams 作业。这需要最新的 OCI Java SDK,并且必须输入主播放列表名称和驻留桶名称。这仅用于演示,不适用于生产用途。



/***********
This is a demo program to create media streams.
This requires the latest java SDK of OCI.
Takes input of the master playlist name and residing bucket name.
This is intended for a demonstration only and not for Production usage.
************/

/***********
1. Accept User Input of Object Storage Bucket name & HLS Master playlist (m3u8).
(Note: This takes only master.m3u8 and not sub-playlists as input)
2. Create Media Client. 
3. Create Distribution Channel.
4. Configure CDN for Distribution Channel.
5. Create Stream Packaging Configuration.
6. Create Asset ID  for the provided input master playlist.
7. Ingest the Asset ID into the Distribution Channel.
8. Create MediaStreams Client with distribution channel as endpoint. 
9. After Ingest complete, generate Session Token. 
10. Display's URL that is HLS streamable. 
************/

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.requests.*;
import com.oracle.bmc.mediaservices.responses.*;
import com.oracle.bmc.mediaservices.model.*;
import com.oracle.bmc.mediaservices.requests.CreateStreamCdnConfigRequest;
import com.oracle.bmc.mediaservices.requests.CreateStreamDistributionChannelRequest;
import com.oracle.bmc.mediaservices.requests.CreateMediaAssetRequest;
import com.oracle.bmc.mediaservices.requests.CreateStreamPackagingConfigRequest;
import com.oracle.bmc.mediaservices.requests.IngestStreamDistributionChannelRequest;
import com.oracle.bmc.mediaservices.responses.CreateMediaAssetResponse;
import com.oracle.bmc.mediaservices.responses.CreateStreamCdnConfigResponse;
import com.oracle.bmc.mediaservices.responses.CreateStreamDistributionChannelResponse;
import com.oracle.bmc.mediaservices.responses.CreateStreamPackagingConfigResponse;
import com.oracle.bmc.mediaservices.responses.IngestStreamDistributionChannelResponse;
import com.oracle.bmc.mediaservices.model.IngestStreamDistributionChannelResult;
import com.oracle.bmc.mediaservices.model.MediaAsset;
import com.oracle.bmc.mediaservices.model.StreamCdnConfig;
import com.oracle.bmc.mediaservices.model.StreamDistributionChannel;
import com.oracle.bmc.mediaservices.model.StreamPackagingConfig;
import com.oracle.bmc.mediaservices.MediaStreamClient;
import com.oracle.bmc.mediaservices.model.CreateStreamDistributionChannelDetails;
import com.oracle.bmc.mediaservices.model.CreateStreamCdnConfigDetails;
import com.oracle.bmc.mediaservices.model.IngestStreamDistributionChannelDetails;
import com.oracle.bmc.mediaservices.requests.CreateStreamDistributionChannelRequest;
import com.oracle.bmc.mediaservices.model.EdgeStreamCdnConfig;
import com.oracle.bmc.mediaservices.model.StreamCdnConfigSection;
import com.oracle.bmc.mediaservices.model.CreateStreamPackagingConfigDetails.StreamPackagingFormat;
import com.oracle.bmc.mediaservices.model.StreamPackagingConfigEncryptionNone;
import com.oracle.bmc.mediaservices.model.AssetType;
import com.oracle.bmc.mediaservices.requests.GenerateSessionTokenRequest;
import com.oracle.bmc.mediaservices.model.GenerateSessionTokenDetails;
import com.oracle.bmc.mediaservices.requests.GetMediaWorkflowJobRequest;
import com.oracle.bmc.mediaservices.responses.GetMediaWorkflowJobResponse;
import com.oracle.bmc.mediaservices.model.MediaWorkflowJob.LifecycleState;

import org.json.simple.*; 
import org.json.simple.parser.*;
import java.util.Collections;
import java.util.*;
import java.util.Scanner;

public class MediastreamsDemoApp {

    // User Input 
    public static String[] getUserInput(){
        String[] inputs = new String[2];
        MediastreamsDemoApp.printString("\n", "Enter name of bucket where master playlist is located:");
        Scanner input = new Scanner(System.in);
        String inputBucketName = input.nextLine();
        MediastreamsDemoApp.printString("\n","Enter name of master playlist to be ingested:");
        String inputPlaylistName = input.nextLine();
        input.close();
        inputs[0] = inputBucketName;
        inputs[1] = inputPlaylistName;
        return inputs;
    }
    // Print Function
    public static void printString(Object stringtoPrint , Object stringtoPrint2){
        System.out.println(stringtoPrint);
        System.out.println(stringtoPrint2);
    }

    // Media Client Creation by default with Instance Principal.
    // Toggle the other java lines in this code for User Principal.
    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);
        return mediaClient;
    }
    // Closing Media Client
    public static void closeMediaService(MediaServicesClient mc,MediaStreamClient ms){
        mc.close();
        ms.close();
        MediastreamsDemoApp.printString("\n", "Media Clients are Closed");
    }
    // Create Media Streams Client 
    // Default this program creates using Instance Principal
    public static MediaStreamClient connectMediaStreams(StreamDistributionChannel dc){
        String endpoint = dc.getDomainName();
        InstancePrincipalsAuthenticationDetailsProvider provider = InstancePrincipalsAuthenticationDetailsProvider.builder().build();
        MediaStreamClient mediaStreamsClient =  new MediaStreamClient(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);
        // MediaStreamClient mediaStreamsClient = MediaStreamClient.builder().build(authenticationDetailsProvider);
        mediaStreamsClient.setEndpoint("https://"+endpoint);
        MediastreamsDemoApp.printString("\n" ,"Media Streams Client Instatiated Successfully");
        return mediaStreamsClient;
    }
    // Create Distribution Channel 
    public static StreamDistributionChannel createDistributionChannel(MediaServicesClient mc, String compartment_id){
        CreateStreamDistributionChannelRequest  request = CreateStreamDistributionChannelRequest.builder().createStreamDistributionChannelDetails(CreateStreamDistributionChannelDetails.builder().displayName("test-java-sdk").compartmentId(compartment_id).build()).build();
        CreateStreamDistributionChannelResponse response = mc.createStreamDistributionChannel(request);
        StreamDistributionChannel dc = response.getStreamDistributionChannel();
        return dc;
    }
    //Create CDN - In this case, its OCI Edge.
    public static void createCDN(MediaServicesClient mc, String compartment_id, StreamDistributionChannel dc){
        String channelId = dc.getId();
        CreateStreamCdnConfigRequest  request = CreateStreamCdnConfigRequest.builder().createStreamCdnConfigDetails(
                                                                        CreateStreamCdnConfigDetails.builder().displayName("test-java-sdk").isEnabled(true).distributionChannelId(channelId).config(EdgeStreamCdnConfig.builder().build()).build()).build();
        CreateStreamCdnConfigResponse response = mc.createStreamCdnConfig(request);
        StreamCdnConfig cdnConfig = response.getStreamCdnConfig();
    }
    // Create Streaming Package Configuration 
    // By default Unencrypted in this code. 
    public static StreamPackagingConfig createStreamPackage(MediaServicesClient mc, StreamDistributionChannel dc){
        String channelId = dc.getId();
        // Unencrypted Stream
        CreateStreamPackagingConfigRequest  request = CreateStreamPackagingConfigRequest.builder().createStreamPackagingConfigDetails(CreateStreamPackagingConfigDetails.builder().displayName("test-java-sdk").distributionChannelId(channelId).streamPackagingFormat(CreateStreamPackagingConfigDetails.StreamPackagingFormat.valueOf("Hls")).segmentTimeInSeconds(6).encryption(StreamPackagingConfigEncryptionNone.builder().build()).build()).build();
        // AES 128 encrypted stream
        //CreateStreamPackagingConfigRequest  request = CreateStreamPackagingConfigRequest.builder().createStreamPackagingConfigDetails(CreateStreamPackagingConfigDetails.builder().displayName("test-java-sdk").distributionChannelId(channelId).streamPackagingFormat(CreateStreamPackagingConfigDetails.StreamPackagingFormat.valueOf("Hls")).segmentTimeInSeconds(6).encryption(StreamPackagingConfigEncryptionAes128.builder().build()).build()).build();
        CreateStreamPackagingConfigResponse response = mc.createStreamPackagingConfig(request);
        StreamPackagingConfig packageConfig = response.getStreamPackagingConfig();
        return packageConfig;
    }
    // Create Media Asset ID for given master playlist 
    public static MediaAsset createAsset(MediaServicesClient mc, String inputBucket,String masterPlayList, String namespace, String compartmentId){
        CreateMediaAssetRequest  request = CreateMediaAssetRequest.builder().createMediaAssetDetails(CreateMediaAssetDetails.builder().bucketName(inputBucket).displayName("test-java-sdk").objectName(masterPlayList).namespaceName(namespace).type(AssetType.valueOf("Playlist")).compartmentId(compartmentId).build()).build();
        CreateMediaAssetResponse response = mc.createMediaAsset(request);
        MediaAsset mediaAsset = response.getMediaAsset();
        return mediaAsset;
    }
    // Ingest the Master Playlist to Distribution Channel 
    public static IngestStreamDistributionChannelResult ingestAsset(MediaServicesClient mc, MediaAsset ma, StreamDistributionChannel dc, String compartmentId){
        String assetId = ma.getId();
        String channelId = dc.getId();
        IngestStreamDistributionChannelRequest request = IngestStreamDistributionChannelRequest.builder().ingestStreamDistributionChannelDetails(AssetMetadataEntryDetails.builder().mediaAssetId(assetId).compartmentId(compartmentId).build()).streamDistributionChannelId(channelId).build();
        IngestStreamDistributionChannelResponse response = mc.ingestStreamDistributionChannel(request);
        IngestStreamDistributionChannelResult ingestResult = response.getIngestStreamDistributionChannelResult();
        return ingestResult;
    }
    // Get the Media WorkflowJob ID for the Ingest Job
    public static MediaWorkflowJob checkIngestJobStatus(MediaServicesClient mc, IngestStreamDistributionChannelResult ingestStatus) {
        String mediaWorkflowId = ingestStatus.getMediaWorkflowJobId(); 
        GetMediaWorkflowJobRequest request = GetMediaWorkflowJobRequest.builder().mediaWorkflowJobId(mediaWorkflowId).build();
        GetMediaWorkflowJobResponse response = mc.getMediaWorkflowJob(request);
        MediaWorkflowJob mediaWorkflowJob = response.getMediaWorkflowJob();
        return mediaWorkflowJob;
    }
    // Check the status of the Ingest Job using above Media Workflow Job ID
    public static String jobLifecycleState(MediaServicesClient mediaClient,IngestStreamDistributionChannelResult ingestStatus){
        MediaWorkflowJob mediaWorkflowJob = MediastreamsDemoApp.checkIngestJobStatus(mediaClient,ingestStatus);
        MediaWorkflowJob.LifecycleState lifestate = mediaWorkflowJob.getLifecycleState();
        String ingestCurrentStatus = lifestate.getValue();
        return ingestCurrentStatus;
    }
    // Create Session Token 
    // Defaults to 24 hour validity 
    public static SessionToken generateSessionToken(MediaStreamClient ms, StreamPackagingConfig sp, MediaAsset ma){
        String streamPackagingId = sp.getId();
        String mediaAssetId = ma.getId();
        List<GenerateSessionTokenDetails.Scopes> scopes = new ArrayList<GenerateSessionTokenDetails.Scopes>();
        scopes.add(GenerateSessionTokenDetails.Scopes.valueOf("Edge")); 
        scopes.add(GenerateSessionTokenDetails.Scopes.valueOf("Playlist"));
        List<String> assetIds = new ArrayList<String>();
        assetIds.add(mediaAssetId);
        GenerateSessionTokenRequest request = GenerateSessionTokenRequest.builder().generateSessionTokenDetails(GenerateSessionTokenDetails.builder().packagingConfigId(streamPackagingId).scopes(scopes).assetIds(assetIds).build()).build();
        GenerateSessionTokenResponse response = ms.generateSessionToken(request);
        SessionToken sessionToken = response.getSessionToken();
        return sessionToken;

    }

    public static void spinningWheel() throws InterruptedException{
        String a = "|/-\\";
        while (true) {
            for (int i = 0; i < 4; i++) {
                System.out.print("\033[0;0H");   // place cursor at top left corner
                for (int j = 0; j < 80; j++) {   // 80 character terminal width, say
                    System.out.print(a.charAt(i));
                }
                Thread.sleep(250);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException{

        // **Variable Declarations** //
        String compartment_id = "ocid1.compartment.oc1..aaaaaaaabhuut4zoztxlfneotrwuauqt5wjhmj4kxaka6ajme4ipxqlcwv6a";
        String namespace = "axjagzvlc4vi";
        
        String [] inputs = MediastreamsDemoApp.getUserInput();
        String inputBucket = inputs[0];
        String masterPlayList = inputs[1];
        // Connect to media services 
        MediaServicesClient mediaClient = MediastreamsDemoApp.connectMediaService();
        MediastreamsDemoApp.printString("\n", "Media Client Instatiated Successfully");
        // Create Distribution Channel
        StreamDistributionChannel distributionChannel = MediastreamsDemoApp.createDistributionChannel(mediaClient, compartment_id);
        MediastreamsDemoApp.printString("\n Distribution Channel Created Successfully",distributionChannel.getId());
        // Configure CDN for the distribution channel
        MediastreamsDemoApp.createCDN(mediaClient, compartment_id, distributionChannel);
        // Create stream packaging Configuration
        StreamPackagingConfig streamPackageConfig = MediastreamsDemoApp.createStreamPackage(mediaClient, distributionChannel);
        MediastreamsDemoApp.printString("\n Streaming Packaging Configuration Created Successfully", streamPackageConfig.getId());
        // Create Media Asset for provided master playlist
        MediaAsset mediaAsset = MediastreamsDemoApp.createAsset(mediaClient, inputBucket, masterPlayList, namespace, compartment_id);
        MediastreamsDemoApp.printString("\n Media Asset Registered Successfully" , mediaAsset.getId());
        // Initiate Ingest of the master playlist into the Distribution channel
        IngestStreamDistributionChannelResult ingestStatus = MediastreamsDemoApp.ingestAsset(mediaClient, mediaAsset, distributionChannel, compartment_id);
        MediastreamsDemoApp.printString("\n Ingest of Asset Initiated with Job", ingestStatus.getMediaWorkflowJobId());
        // Run Loop for ingest job to complete.      
        boolean status = false;
        System.out.print("Ingesting");
        while (!status){
            String ingestValue = MediastreamsDemoApp.jobLifecycleState(mediaClient,ingestStatus);
            System.out.print(".");
            Thread.sleep(3000);
            //System.out.println(ingestCurrentStatus);
            if ((ingestValue == "SUCCEEDED") || (ingestValue == "FAILED")){
                break;
            }
        }
        String ingestOutcome = MediastreamsDemoApp.jobLifecycleState(mediaClient,ingestStatus);
        MediastreamsDemoApp.printString("\nIngest Completed with status", ingestOutcome);

        if (ingestOutcome == "SUCCEEDED") {
            // Create media Streams Client with distribution cahnnel 
            MediaStreamClient mediaStreamsClient = MediastreamsDemoApp.connectMediaStreams(distributionChannel);
            // Generate session token for the master playlist.
            SessionToken sessionToken = MediastreamsDemoApp.generateSessionToken(mediaStreamsClient, streamPackageConfig, mediaAsset);
            //MediastreamsDemoApp.printString(sessionToken.getToken());
            MediastreamsDemoApp.printString("\n\nStream Media with your player:\n\n","https://"+distributionChannel.getDomainName()+"/20211101/actions/generatePlaylist?mediaAssetId="+mediaAsset.getId()+"&streamPackagingConfigId="+streamPackageConfig.getId()+"&token="+sessionToken.getToken());
            // Close the Media Clients
            MediastreamsDemoApp.closeMediaService(mediaClient,mediaStreamsClient);
        }
        else {
            mediaClient.close();
        }

    }
}
	

OCI Media Streams 的使用场景

  • 访问和打包视频内容

    使用 OCI Media Streams,通过资产 ID 更轻松地访问存储的视频。OCI Media Streams 会将内容打包在一起,因此您只需对内容进行一次转码,即可在各种设备类型和格式上进行流式传输。此服务将动态应用内容加密和流格式,以尽可能节省开发人员的时间和精力。

  • 剪辑视频

    在 OCI Media Flow 为热门的社交媒体网站提供合适的视频格式后,OCI Media Streams 将对视频内容进行打包并加密,以便从各种设备(包括手机和游戏机)进行流式传输。

  • 创建学习平台

    使用 OCI Media Flow 为学习平台体验创建、处理和存储视频,然后使用 OCI Media Streams 打包并加密内容,以实现安全传输和流式传输。强大的内容加密方法可确保您的视频只在您希望的位置传输。

Media Streams 的资源

2022 年 7 月 20 日

Oracle 推出 OCI Digital Media Services,加速 OCI 中的视频运营

甲骨文公司首席产品经理 Remi Fourreau

我们很高兴宣布 Oracle Cloud Infrastructure (OCI) 中的 Digital Media Services (DMS) 已全面上市。拥有视频内容的 OCI 客户可以利用低成本的媒体处理功能以及 DMS Media Flow 和 DMS Media Streams 服务的媒体分发功能。这些服务可以使用新的媒体功能来增强应用和业务流程,从而创造更好的客户体验并改善业务运营。

阅读全文

精选博客

查看全部

赶快行动

享用 Always Free 云技术服务,并试用 30 天的收费服务

Oracle 提供的 Free Tier 无时间限制,包含了 Media Streams、Media Flow、AI Services 等服务,另外还有 300 美元的免费储值,让您可以试用其他云技术服务。立即获取详细信息并注册您的免费账户。

  • Oracle Cloud Free Tier 包含哪些内容?

    • 永久免费
    • 2 个 Autonomous Database,各 20 GB
    • 计算虚拟机
    • 100 GB 块存储卷
    • 10 GB 对象存储空间

联系销售

想了解更多有关 Media Streams 的信息?让我们的专家为您提供帮助。

  • 专家能为您解答以下问题:

    • 哪些服务与 OCI Media Streams 无缝集成?
    • 我的方案定价是怎样的?
    • 如何保护我的视频内容分发?

注:为免疑义,本网页所用以下术语专指以下含义:

  1. 除Oracle隐私政策外,本网站中提及的“Oracle”专指Oracle境外公司而非甲骨文中国 。
  2. 相关Cloud或云术语均指代Oracle境外公司提供的云技术或其解决方案。