使用Kinesis Video Streams上传视频

目标:使用Java接入KVS,完成视频上传后可以在控制台查看,模拟视频设备从接口获取到临时密钥,然后进行视频的传输的流程

本文章主要解决:

  • 运行GitHub上项目时缺失dll的问题
  • 使用STS获取到临时密钥,取代项目从环境变量获取密钥的方式
  • 切割本地的视频文件然后上传

KVS的JAVA示例项目

启动 Demoapp 示例应用程序

  1. 使用sts获取临时密钥

    private static void get(){
            String voiceArm = "arn:aws:kinesisvideo:us-west-2:xxxxxx:stream/test/xxxxx";
            String signalArm = "arn:aws:kinesisvideo:us-west-2:xxxx:channel/test/xxxx";
            BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials("awsAccessKey","awsSecretKey");
            AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder
                    .standard()
                    .withCredentials(new AWSCredentialsProviderChain(new AWSStaticCredentialsProvider(basicAWSCredentials)))
                    .withRegion("us-west-2")
                    .build();
    
            GetFederationTokenRequest getFederationTokenRequest = new GetFederationTokenRequest();
            //设置有效时间
            getFederationTokenRequest.setDurationSeconds(5 * 60 * 60);
            getFederationTokenRequest.setName("kvs");
            //设置超时时间
            getFederationTokenRequest.setSdkRequestTimeout(60 * 1000);
    
    
            // Define the policy and add it to the request.
            Policy policy = new Policy();
            policy.withStatements(new Statement(Statement.Effect.Allow)
                    .withActions(() -> "kinesisvideo:*")
                    .withResources( new Resource("arn:aws:kinesisvideo:*:xxxxx:channel/*/*"),new Resource("arn:aws:kinesisvideo:*:xxxx:stream/*/*")));
            getFederationTokenRequest.setPolicy(policy.toJson());
    
            // 获取临时凭证
            GetFederationTokenResult federationToken = stsClient.getFederationToken(getFederationTokenRequest);
            Credentials sessionCredentials = federationToken.getCredentials();
            System.out.println(sessionCredentials);
        }
    
  2. 修改main方法,基于AWS STS获取到的密钥,进行视频流的上传

     public static void main(final String[] args) throws Exception {
            //sts生成的临时密钥
            String awsAccessKey = "you awsAccessKey";
            String awsSecretKey = "you awsSecretKey";
            String sessionToken = "you sessionToken";
            BasicSessionCredentials basicSessionCredentials = new BasicSessionCredentials(awsAccessKey,awsSecretKey,sessionToken);
    
    
            try {
                // create Kinesis Video high level client
    
                final KinesisVideoClient kinesisVideoClient = KinesisVideoJavaClientFactory
                        .createKinesisVideoClient(
                                Regions.US_WEST_2,new AWSStaticCredentialsProvider(basicSessionCredentials)
                                );
    
                // create a media source. this class produces the data and pushes it into
                // Kinesis Video Producer lower level components
                //final MediaSource mediaSource = createImageFileMediaSource();
    
                // Audio/Video sample is available for playback on HLS (Http Live Streaming)
                final MediaSource mediaSource = createImageFileMediaSource();
    
                // register media source with Kinesis Video Client
                kinesisVideoClient.registerMediaSource(mediaSource);
    
                // start streaming
                mediaSource.start();
            } catch (final KinesisVideoException e) {
                throw new RuntimeException(e);
            }
        }
    
  3. 修改方法,配置dll插件,dll下载地址,注意选择64位的dll插件

        private boolean loadNativeLibraryIndirect(final @Nonnull String libraryName) {
            try {
                System.out.println(System.getProperty("java.library.path"));
                System.loadLibrary("kernel32");
                System.loadLibrary("ucrtbased");
                System.loadLibrary("vcruntime140d");
                System.loadLibrary("vcruntime140_1d");
    
    
                System.loadLibrary(libraryName);
    
    
                mLog.trace("Success! Indirectly loaded native library {}.", libraryName);
                return true;
            } catch (final UnsatisfiedLinkError e) {
                mLog.error("Unsatisfied link error.", e);
            } catch (final SecurityException e) {
                mLog.error("Security exception.", e);
            }
    
            // This is the error return case.
            return false;
        }
    
  4. 在idea配置依赖的原生库,就是ddl所在插件的目录

    image-20230308113145514

  5. 配置好后可以直接运行DemoAppMain,会上传项目中提前配好的视频,然后可以在控制台查看到视频

    image-20230601180811975

上传本地视频

使用GStreamer插件对需要上传的视频进行切割,Windows安装GStreamer教程,进行到安装目录/bin,执行指令如下

.\gst-launch-1.0.exe filesrc location=D:\\FFOutput\\test.mkv ! decodebin ! videorate ! videoscale ! x264enc pass=qual quantizer=20 speed-preset=4 tune=zerolatency bitrate=1024 key-int-max=25 ! video/x-h264,stream-format=avc,alignment=au,profile=baseline,width=1920,height=1080,framerate=25/1 ! multifilesink location=D:\\FFOutput\\test1\\frame-%03d.h264 index=1

这条指令使用 GStreamer 库中的 gst-launch-1.0.exe 工具,将位于 D:\FFOutput\test.mkv 的视频文件解码并进行编码处理,然后将编码后的视频按帧输出到 D:\FFOutput\test1 目录下,并以 frame-001.h264、frame-002.h264 等命名。

具体参数含义如下:

  • filesrc:输入元素,从指定路径读取输入媒体文件。
    • location=D:\FFOutput\test.mkv:指定输入文件路径为 D:\FFOutput\test.mkv。
  • decodebin:解码器元素,根据输入媒体格式自动选择正确的解码器进行解码。在此处,它接受 filesrc 元素的输出流作为输入。
  • videorate:视频帧率调整元素,通过插入或删除视频帧来调整帧率。
  • videoscale:视频大小调整元素,通过缩放视频帧来调整分辨率。
  • x264enc:软件 H.264 编码器元素,对解码后的视频进行重新编码。
    • pass=qual:设置质量优先(Quality-first)模式。
    • quantizer=20:设置目标量化器值(Target Quantizer Value),范围为 0 到 51,值越小,视频质量越好,但比特率也会更高。
    • speed-preset=4:设置速度预设(Speed preset),范围为 0 到 8,值越小,编码速度越慢,视频质量越好。
    • tune=zerolatency:设置编码器偏好(Encoder Tune),为 “zerolatency”,表示最小化延迟。
    • bitrate=1024:设置输出比特率为 1024 kbps。
    • key-int-max=25:设置 GOP(Group of Pictures)最大间隔为 25 帧。GOP 表示一组关键帧和非关键帧的序列。
  • video/x-h264,stream-format=avc,alignment=au,profile=baseline,width=1920,height=1080,framerate=25/1:输出视频流格式,包括 H.264 视频编码器属性和视频分辨率、帧率等信息。
    • video/x-h264:表示输出视频流格式为 H.264 格式。
    • stream-format=avc:表示使用 AVC(Advanced Video Coding)封装格式。
    • alignment=au:表示每个 NALU(Network Abstraction Layer Unit)后面会有一个 Access Unit(AU)。
    • profile=baseline:表示使用 baseline 级别的 H.264 编码格式。
    • width=1920,height=1080:表示输出视频分辨率为 1920x1080。
    • framerate=25/1:表示输出视频帧率为 25 帧/秒。
  • multifilesink:多文件输出元素,将编码后的视频帧写入磁盘。
    • location=D:\FFOutput\test1\frame-%03d.h264:指定输出文件路径及文件名,其中 %03d 表示 3 位数字的序号,例如 frame-001.h264。
    • index=1:指定起始序号为 1。

最后修改DemoAppMain类中,文件目录改为被切割视频文件存放目录,进行上传,在KVS网页端查看视频

image-20230601180803191