Krzysztof Madej
Krzysztof Madej

Reputation: 40663

How to put an image overlay over video

I want to put an image overlay over video, but I'm not sure how I can do this. I'm trying to modify example from this repo Azure Media Services v3 .NET Core tutorials , bascially what I changed here is transform:

private static Transform EnsureTransformForOverlayExists(IAzureMediaServicesClient client, string resourceGroupName, string accountName, string transformNameNew)
{
    Console.WriteLine(transformNameNew);

    Transform transform = client.Transforms.Get(resourceGroupName, accountName, transformName);

    if (transform == null)
    {
        TransformOutput[] outputs = new TransformOutput[]
        {
                    new TransformOutput(
  new StandardEncoderPreset(
    codecs: new Codec[]
    {
      new AacAudio(
        channels: 2,
        samplingRate: 48000,
        bitrate: 128000,
        profile: AacAudioProfile.AacLc
      ),
      new H264Video(stretchMode: "AutoFit",
        keyFrameInterval: TimeSpan.FromSeconds(2),
        layers: new[]
        {
          new H264Layer(
            bitrate: 1500000,
            maxBitrate: 1500000,
            width: "640",
            height: "360"
          )
        }
      ),
      new PngImage(
          start: "25%",
          step: "25%",
          range: "80%",
          layers: new PngLayer[]{
              new PngLayer(
                  width: "50%",
                  height: "50%"
              )
          }
      ),
    },
    filters: new Filters
    {
        Overlays = new List<Overlay>
        {
            new VideoOverlay("input1")
        }
    },
    formats: new Format[]
    {
      new Mp4Format(
        filenamePattern: "{Basename}_letterbox{Extension}"
      ),
      new PngFormat(
        filenamePattern: "{Basename}_{Index}_{Label}_{Extension}"
      ),
    }
  ))
        };

        transform = client.Transforms.CreateOrUpdate(resourceGroupName, accountName, transformName, outputs);
    }

    return transform;
}

and RunAsync method to provide multiple inputs where one of them should be an overlay:

private static async Task RunAsync(ConfigWrapper config)
{

    IAzureMediaServicesClient client = await CreateMediaServicesClientAsync(config);
    // Set the polling interval for long running operations to 2 seconds.
    // The default value is 30 seconds for the .NET client SDK
    client.LongRunningOperationRetryTimeout = 2;

    try
    {

        // Ensure that you have customized encoding Transform.  This is really a one time setup operation.
        Transform overlayTransform = EnsureTransformForOverlayExists(client, config.ResourceGroup, config.AccountName, transformName);

        // Creating a unique suffix so that we don't have name collisions if you run the sample
        // multiple times without cleaning up.
        string uniqueness = Guid.NewGuid().ToString().Substring(0, 13);

        string jobName = "job-" + uniqueness;
        string inputAssetName = "input-" + uniqueness;
        string outputAssetName = "output-" + uniqueness;


        Asset asset = client.Assets.CreateOrUpdate(config.ResourceGroup, config.AccountName, inputAssetName, new Asset());

        var inputs = new JobInputs(new List<JobInput>());

        var input = new JobInputHttp(
                            baseUri: "https://nimbuscdn-nimbuspm.streaming.mediaservices.windows.net/2b533311-b215-4409-80af-529c3e853622/",
                            files: new List<String> {"Ignite-short.mp4"},
                            label:"input1"
                            );
        
        inputs.Inputs.Add((input));

        input = new JobInputHttp(
            baseUri: "SomeBaseUriHere",
            files: new List<string> {"AssetVideo_000001_None_.png"}, 
            label: "overlay");

        inputs.Inputs.Add((input));

        Asset outputAsset = CreateOutputAsset(client, config.ResourceGroup, config.AccountName, outputAssetName);

        Job job = SubmitJob(client, config.ResourceGroup, config.AccountName, transformName, jobName, inputs, outputAsset.Name);

        DateTime startedTime = DateTime.Now;

        job = WaitForJobToFinish(client, config.ResourceGroup, config.AccountName, transformName, jobName);

        TimeSpan elapsed = DateTime.Now - startedTime;

        if (job.State == JobState.Finished)
        {
            Console.WriteLine("Job finished.");
            if (!Directory.Exists(outputFolder))
                Directory.CreateDirectory(outputFolder);
            await MakeContainerPublic(client, config.ResourceGroup, config.AccountName, outputAsset.Name, config.BlobConnectionString);
            DownloadResults(client, config.ResourceGroup, config.AccountName, outputAsset.Name, outputFolder).Wait();
        }
        else if (job.State == JobState.Error)
        {
            Console.WriteLine($"ERROR: Job finished with error message: {job.Outputs[0].Error.Message}");
            Console.WriteLine($"ERROR:                   error details: {job.Outputs[0].Error.Details[0].Message}");
        }
    }
    catch(ApiErrorException ex)
    {
        string code = ex.Body.Error.Code;
        string message = ex.Body.Error.Message;

        Console.WriteLine("ERROR:API call failed with error code: {0} and message: {1}", code, message);

    }          
}

But I have this error

Microsoft.Cloud.Media.Encoding.PresetException: Preset ERROR: There are 2 input assets. Preset has 2 Source but does NOT specify AssetID for each Source and I have no idea how to overcome this.

Upvotes: 0

Views: 206

Answers (1)

Jason Pan
Jason Pan

Reputation: 21916

At this time, it is not possible to use v3 APIs to create overlays. The feature is not fully implemented. See this link for other gaps between the v2 and v3 APIs.

For more details, you can see this site .

Upvotes: 1

Related Questions