Loupe

Concaténer 2 (ou plusieurs) vidéos grâce à Azure Media Services

Récemment, je cherchais un moyen de concaténer, par programmation, 2 videos (par exemple pour mettre un trailer ou une publication avant/après une vidéo). Il s'avère que Azure Media Services propose, dans son arsenal, tout ce qu'il faut pour réaliser cette action, comme nous allons le voir!

La première étape, pour concaténer nos vidéos, est déjà de les uploader dans le storage Azure correspondant à notre Media Services. Pour cela, il n'y a pas de grandes difficultés, le SDK vous simplifie énormément la vie:

public static async Task<IAsset> CreateAssetFromFileAsync(string filePath)
{
    var assetName = Path.GetFileNameWithoutExtension(filePath);

    var asset = await _cloudMediaContext.Assets.CreateAsync(assetName, AssetCreationOptions.None, CancellationToken.None);
    var assetFile = await asset.AssetFiles.CreateAsync(Path.GetFileName(filePath), CancellationToken.None);

    assetFile.UploadProgressChanged += (s, e) =>
    {
        Console.WriteLine($"Upload: {e.Progress}");
    };
    assetFile.Upload(filePath);

    return asset;
}

L'objet "_cloudMediaContext" est une instance de la classe CloudMediaContext, qui permet de se connecter à votre Media Services pour travailler avec (je vous passe les détails sur la partie "authentification", ce n'est pas le point le plus intéressant):

var tokenCredentials = new AzureAdTokenCredentials(_tenant,
                                        new AzureAdClientSymmetricKey(_clientId, _clientSecret),
                                        AzureEnvironments.AzureCloudEnvironment);

var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

_cloudMediaContext = new CloudMediaContext(new Uri(_restApi), tokenProvider);

Une fois les vidéos uploadées, il convient alors de lancer un job Media Services en lui indiquant une configuration spécifique (un fichier XML ou JSON) qui va contenir les instructions à réaliser, à savoir la concaténation des vidéos:

{
  "Version": 1.0,
  "Sources": [
    {
      "AssetID": "{FIRST_VIDEO_ASSET_ID}",
      "StartTime": "00:00:00",
      "Duration": "00:01:02"
    },
    {
      "AssetID": "{SECOND_VIDEO_ASSET_ID}",
      "StartTime": "00:00:00",
      "Duration": "00:00:21"
    }
  ],
  "Codecs": [
    {
      "KeyFrameInterval": "00:00:02",
      "SceneChangeDetection": true,
      "H264Layers": [
        {
          "Level": "auto",
          "Bitrate": 1800,
          "MaxBitrate": 1800,
          "BufferWindow": "00:00:05",
          "BFrames": 3,
          "ReferenceFrames": 3,
          "AdaptiveBFrame": true,
          "Type": "H264Layer",
          "Width": "640",
          "Height": "360",
          "FrameRate": "0/1"
        }
      ],
      "Type": "H264Video"
    },
    {
      "Channels": 2,
      "SamplingRate": 48000,
      "Bitrate": 128,
      "Type": "AACAudio"
    }
  ],
  "Outputs": [
    {
      "FileName": "{Basename}_{Width}x{Height}_{VideoBitrate}.mp4",
      "Format": {
        "Type": "MP4Format"
      }
    }
  ]
}

Comme vous pouvez le constater, le noeud "Sources" contient les différents assets Media Services qui seront utilisés. Il est important de connaitre l'identifiant, la durée de la vidéo et à partir de quel moment de la vidéo vous voulez que la concaténation ait lieu. On remarquera que, pour les besoins de la démo, la durée et le moment en question ont été saisis en durs mais il est tout à fait possible de récupérer ces informations depuis Media Services! Seuls les identifiants des vidéos ont été gérés de manière dynamique par soucis de simplicité.

A présent, il ne reste plus qu'à créer le job correspondant et à le soumettre:

var processor = _cloudMediaContext.MediaProcessors.GetLatestMediaProcessorByName(MediaProcessorNames.MediaEncoderStandard);

var job = _cloudMediaContext.Jobs.Create("Videos Merge");
var task = job.Tasks.AddNew("Media Encoder Standard encoding task", processor, videoMergeConfigFileContent, TaskOptions.None);

task.InputAssets.Add(firstVideoAsset);
task.InputAssets.Add(secondVideoAsset);

task.OutputAssets.AddNew("MergedVideo", AssetCreationOptions.None);

job.Submit();

job = job.StartExecutionProgressTask(j =>
{
    Console.WriteLine("Current job state: {0}", j.State);
    Console.WriteLine("Current job progress: {0}", j.GetOverallProgress());
}, CancellationToken.None).GetAwaiter().GetResult();

Console.WriteLine("Job done!");

Une fois le traitement terminé, on se retrouve avec une vidéo qui est, en fait, la concaténation de 2 autres vidéos:

C'est simple, rapide et efficace! :)

 

Happy coding!

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus