如何使用 Media Encoder Standard 通过 .NET 来生成缩略图How to generate thumbnails using Media Encoder Standard with .NET

可以使用 Media Encoder Standard 以 JPEGPNGBMP 图像文件格式从输入视频生成一个或多个缩略图。You can use Media Encoder Standard to generate one or more thumbnails from your input video in JPEG, PNG, or BMP image file formats. 可以提交仅生成图像的任务,也可以合并缩略图生成与编码功能。You can submit Tasks that produce only images, or you can combine thumbnail generation with encoding. 本文针对此类方案提供一些示例 XML 和 JSON 缩略图预设。This article provides a few sample XML and JSON thumbnail presets for such scenarios. 本文的末尾提供了一段示例代码,演示如何使用媒体服务 .NET SDK 来完成编码任务。At the end of the article, there is a sample code that shows how to use the Media Services .NET SDK to accomplish the encoding task.

有关示例预设中使用的元素的更多详细信息,请查看 Media Encoder Standard 架构For more details on the elements that are used in sample presets, you should review Media Encoder Standard schema.

请务必仔细阅读 注意事项 部分。Make sure to review the Considerations section.

“单个 PNG 文件”预设示例Example of a "single PNG file" preset

使用以下 JSON 和 XML 预设可以基于输入视频的前几秒内容生成单个输出 PNG 文件,其中的编码器会尽力尝试查找“相关的”帧。The following JSON and XML preset can be used to produce a single output PNG file from the first few seconds of the input video, where the encoder makes a best-effort attempt at finding an “interesting” frame. 请注意,输出图像尺寸已设置为 100%,这意味着,这些尺寸与输入视频的尺寸匹配。Note that the output image dimensions have been set to 100%, meaning these match the dimensions of the input video. 另请注意需要如何指定“Outputs”中“Format”设置,以匹配“Codecs”节中“PngLayers”的用法。Note also how the “Format” setting in "Outputs" is required to match the use of "PngLayers" in the “Codecs” section.

JSON 预设JSON preset

    {
      "Version": 1.0,
      "Codecs": [
        {
          "PngLayers": [
            {
              "Type": "PngLayer",
              "Width": "100%",
              "Height": "100%"
            }
          ],
          "Start": "{Best}",
          "Type": "PngImage"
        }
      ],
      "Outputs": [
        {
          "FileName": "{Basename}_{Index}{Extension}",
          "Format": {
            "Type": "PngFormat"
          }
        }
      ]
    }

XML 预设XML preset

    <?xml version="1.0" encoding="utf-16"?>
    <Preset xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" Version="1.0" xmlns="https://www.windowsazure.com/media/encoding/Preset/2014/03">
      <Encoding>
        <PngImage Start="{Best}">
          <PngLayers>
            <PngLayer>
              <Width>100%</Width>
              <Height>100%</Height>
            </PngLayer>
          </PngLayers>
        </PngImage>
      </Encoding>
      <Outputs>
        <Output FileName="{Basename}_{Index}{Extension}">
          <PngFormat />
        </Output>
      </Outputs>
    </Preset>

“一系列 JPEG 图像”预设的示例Example of a "series of JPEG images" preset

可以使用以下 JSON 和 XML 预设在输入时间线的 5%、15% ... 95% 时间戳处生成一组 10 幅图像,其中的图像大小指定为输入视频的四分之一。The following JSON and XML preset can be used to produce a set of 10 images at timestamps of 5%, 15%, …, 95% of the input timeline, where the image size is specified to be one quarter that of the input video.

JSON 预设JSON preset

    {
      "Version": 1.0,
      "Codecs": [
        {
          "JpgLayers": [
            {
              "Quality": 90,
              "Type": "JpgLayer",
              "Width": "25%",
              "Height": "25%"
            }
          ],
          "Start": "5%",
          "Step": "10%",
          "Range": "96%",
          "Type": "JpgImage"
        }
      ],
      "Outputs": [
        {
          "FileName": "{Basename}_{Index}{Extension}",
          "Format": {
            "Type": "JpgFormat"
          }
        }
      ]
    }

XML 预设XML preset

    <?xml version="1.0" encoding="utf-16"?>
    <Preset xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" Version="1.0" xmlns="https://www.windowsazure.com/media/encoding/Preset/2014/03">
      <Encoding>
        <JpgImage Start="5%" Step="10%" Range="96%">
          <JpgLayers>
            <JpgLayer>
              <Width>25%</Width>
              <Height>25%</Height>
              <Quality>90</Quality>
            </JpgLayer>
          </JpgLayers>
        </JpgImage>
      </Encoding>
      <Outputs>
        <Output FileName="{Basename}_{Index}{Extension}">
          <JpgFormat />
        </Output>
      </Outputs>
    </Preset>

“在特定时间戳处生成一个图像”预设示例Example of a "one image at a specific timestamp" preset

可以使用以下 JSON 和 XML 预设在输入视频的 30 秒标记处生成单个 JPEG 图像。The following JSON and XML preset can be used to produce a single JPEG image at the 30-second mark of the input video. 此预设预期输入视频的持续时间超过 30 秒(否则作业失败)。This preset expects the input video to be more than 30 seconds in duration (else the job fails).

JSON 预设JSON preset

    {
      "Version": 1.0,
      "Codecs": [
        {
          "JpgLayers": [
            {
              "Quality": 90,
              "Type": "JpgLayer",
              "Width": "25%",
              "Height": "25%"
            }
          ],
          "Start": "00:00:30",
          "Step": "1",
          "Range": "1",
          "Type": "JpgImage"
        }
      ],
      "Outputs": [
        {
          "FileName": "{Basename}_{Index}{Extension}",
          "Format": {
            "Type": "JpgFormat"
          }
        }
      ]
    }

XML 预设XML preset

    <?xml version="1.0" encoding="utf-16"?>
    <Preset xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" Version="1.0" xmlns="https://www.windowsazure.com/media/encoding/Preset/2014/03">
      <Encoding>
        <JpgImage Start="00:00:30" Step="00:00:01" Range="00:00:01">
          <JpgLayers>
            <JpgLayer>
              <Width>25%</Width>
              <Height>25%</Height>
              <Quality>90</Quality>
            </JpgLayer>
          </JpgLayers>
        </JpgImage>
      </Encoding>
      <Outputs>
        <Output FileName="{Basename}_{Index}{Extension}">
          <JpgFormat />
        </Output>
      </Outputs>
    </Preset>

“不同分辨率的缩略图”预设示例Example of a "thumbnails at different resolutions" preset

可使用以下预设在同一个任务中的不同解决方案下生成缩略图。The following preset can be used to generate thumbnails at different resolutions in one task. 在该示例中,当输入时间线位于 5%、15%、…、95% 时,编码器在两个时点各生成一个图像 - 一个是输入视频分辨率的 100% 处,一个是 50% 处。In the example, at positions 5%, 15%, …, 95% of the input timeline, the encoder generates two images – one at 100% of the input video resolution and the other at 50%.

请注意 FileName 中 {Resolution} 宏的使用;它指示在生成输出图像的文件名时,编码器要使用在预设的“编码”部分中所指定的宽度和高度。Note the use of {Resolution} macro in the FileName; it indicates to the encoder to use the width and height that you specified in the Encoding section of the preset while generating the file name of the output images. 这还能够帮助轻松区分不同图像This also helps you distinguish between the different images easily

JSON 预设JSON preset

    {
      "Version": 1.0,
      "Codecs": [
        {
          "JpgLayers": [
        {
          "Quality": 90,
          "Type": "JpgLayer",
          "Width": "100%",
          "Height": "100%"
        },
        {
          "Quality": 90,
          "Type": "JpgLayer",
          "Width": "50%",
          "Height": "50%"
        }

          ],
          "Start": "5%",
          "Step": "10%",
          "Range": "96%",
          "Type": "JpgImage"
        }
      ],
      "Outputs": [
        {
          "FileName": "{Basename}_{Resolution}_{Index}{Extension}",
          "Format": {
        "Type": "JpgFormat"
          }
        }
      ]
    }

XML 预设XML preset

    <?xml version="1.0" encoding="utf-8"?>
    <Preset xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" Version="1.0" xmlns="https://www.windowsazure.com/media/encoding/Preset/2014/03">
    <Encoding>
    <JpgImage Start="5%" Step="10%" Range="96%"><JpgImage Start="00:00:01" Step="00:00:15">
      <JpgLayers>
       <JpgLayer>
        <Width>100%</Width>
        <Height>100%</Height>
        <Quality>90</Quality>
       </JpgLayer>
       <JpgLayer>
        <Width>50%</Width>
        <Height>50%</Height>
        <Quality>90</Quality>
       </JpgLayer>
      </JpgLayers>
    </JpgImage>
    </Encoding>
    <Outputs>
      <Output FileName="{Basename}_{Resolution}_{Index}{Extension}">
        <JpgFormat/>
      </Output>
    </Outputs>
    </Preset>

在编码时生成缩略图的示例Example of generating a thumbnail while encoding

上述所有示例都在讨论如何提交仅生成图像的编码任务,但还可以将视频/音频编码与缩略图生成结合起来。While all of the above examples have discussed how you can submit an encoding task that only produces images, you can also combine video/audio encoding with thumbnail generation. 以下的 JSON 和 XML 预设指示 Media Encoder Standard 在编码过程中生成一个缩略图 。The following JSON and XML preset tell Media Encoder Standard to generate a thumbnail during encoding.

JSON 预设JSON preset

有关架构的信息,请参阅文。For information about schema, see this article.

    {
      "Version": 1.0,
      "Codecs": [
        {
          "KeyFrameInterval": "00:00:02",
          "SceneChangeDetection": "true",
          "H264Layers": [
            {
              "Profile": "Auto",
              "Level": "auto",
              "Bitrate": 4500,
              "MaxBitrate": 4500,
              "BufferWindow": "00:00:05",
              "Width": 1280,
              "Height": 720,
              "ReferenceFrames": 3,
              "EntropyMode": "Cabac",
              "AdaptiveBFrame": true,
              "Type": "H264Layer",
              "FrameRate": "0/1"
    
            }
          ],
          "Type": "H264Video"
        },
        {
          "JpgLayers": [
            {
              "Quality": 90,
              "Type": "JpgLayer",
              "Width": "100%",
              "Height": "100%"
            }
          ],
          "Start": "{Best}",
          "Type": "JpgImage"
        },
        {
          "Channels": 2,
          "SamplingRate": 48000,
          "Bitrate": 128,
          "Type": "AACAudio"
        }
      ],
      "Outputs": [
        {
          "FileName": "{Basename}_{Index}{Extension}",
          "Format": {
            "Type": "JpgFormat"
          }
        },
        {
          "FileName": "{Basename}_{Resolution}_{VideoBitrate}.mp4",
          "Format": {
            "Type": "MP4Format"
          }
        }
      ]
    }

XML 预设XML preset

有关架构的信息,请参阅文。For information about schema, see this article.

    <?xml version="1.0" encoding="utf-16"?>
    <Preset xmlns:xsd="https://www.w3.org/2001/XMLSchema" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" Version="1.0" xmlns="https://www.windowsazure.com/media/encoding/Preset/2014/03">
      <Encoding>
        <H264Video>
          <KeyFrameInterval>00:00:02</KeyFrameInterval>
          <SceneChangeDetection>true</SceneChangeDetection>
          <H264Layers>
            <H264Layer>
              <Bitrate>4500</Bitrate>
              <Width>1280</Width>
              <Height>720</Height>
              <FrameRate>0/1</FrameRate>
              <Profile>Auto</Profile>
              <Level>auto</Level>
              <BFrames>3</BFrames>
              <ReferenceFrames>3</ReferenceFrames>
              <Slices>0</Slices>
              <AdaptiveBFrame>true</AdaptiveBFrame>
              <EntropyMode>Cabac</EntropyMode>
              <BufferWindow>00:00:05</BufferWindow>
              <MaxBitrate>4500</MaxBitrate>
            </H264Layer>
          </H264Layers>
        </H264Video>
        <AACAudio>
          <Profile>AACLC</Profile>
          <Channels>2</Channels>
          <SamplingRate>48000</SamplingRate>
          <Bitrate>128</Bitrate>
        </AACAudio>
        <JpgImage Start="{Best}">
          <JpgLayers>
            <JpgLayer>
              <Width>100%</Width>
              <Height>100%/Height>
              <Quality>90</Quality>
            </JpgLayer>
          </JpgLayers>
        </JpgImage>
      </Encoding>
      <Outputs>
        <Output FileName="{Basename}_{Resolution}_{VideoBitrate}.mp4">
          <MP4Format />
        </Output>
        <Output FileName="{Basename}_{Index}{Extension}">
          <JpgFormat />
        </Output>
      </Outputs>
    </Preset>   

编码视频并使用 .NET 生成缩略图Encode video and generate thumbnail with .NET

以下代码示例使用媒体服务 .NET SDK 执行下列任务:The following code example uses Media Services .NET SDK to perform the following tasks:

  • 创建编码作业。Create an encoding job.

  • 获取对 Media Encoder Standard 编码器的引用。Get a reference to the Media Encoder Standard encoder.

  • 加载预设 XMLJSON,包含有编码预设以及生成缩略图所需的信息。Load the preset XML or JSON that contain the encoding preset as well as information needed to generate thumbnails. 可以在某一文件中保存此 XMLJSON,并使用以下代码来加载该文件。You can save this XML or JSON in a file and use the following code to load the file.

      // Load the XML (or JSON) from the local file.
      string configuration = File.ReadAllText(fileName);  
    
  • 将一个编码任务添加到该作业。Add a single encoding task to the job.

  • 指定要编码的输入资产。Specify the input asset to be encoded.

  • 创建包含所编码资产的输出资产。Create an output asset that contains the encoded asset.

  • 添加事件处理程序以检查作业进度。Add an event handler to check the job progress.

  • 提交作业。Submit the job.

有关如何设置开发环境的指导,请参阅使用 .NET 进行媒体服务开发一文。See the Media Services development with .NET article for directions on how to set up your dev environment.

using System;
using System.Configuration;
using System.IO;
using System.Linq;
using Microsoft.WindowsAzure.MediaServices.Client;
using System.Threading;

namespace EncodeAndGenerateThumbnails
{
    class Program
    {
        // Read values from the App.config file.
        private static readonly string _AADTenantDomain =
        ConfigurationManager.AppSettings["AMSAADTenantDomain"];
        private static readonly string _RESTAPIEndpoint =
        ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"];
        private static readonly string _AMSClientId =
        ConfigurationManager.AppSettings["AMSClientId"];
        private static readonly string _AMSClientSecret =
        ConfigurationManager.AppSettings["AMSClientSecret"];

        private static CloudMediaContext _context = null;

        private static readonly string _mediaFiles =
        Path.GetFullPath(@"../..\Media");

        private static readonly string _singleMP4File =
            Path.Combine(_mediaFiles, @"BigBuckBunny.mp4");

        static void Main(string[] args)
        {
            AzureAdTokenCredentials tokenCredentials =
                new AzureAdTokenCredentials(_AADTenantDomain,
                    new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret),
                    AzureEnvironments.AzureChinaCloudEnvironment);

            var tokenProvider = new AzureAdTokenProvider(tokenCredentials);

            _context = new CloudMediaContext(new Uri(_RESTAPIEndpoint), tokenProvider);

            // Get an uploaded asset.
            var asset = _context.Assets.FirstOrDefault();

            // Encode and generate the thumbnails.
            EncodeToAdaptiveBitrateMP4Set(asset);

            Console.ReadLine();
        }

        static public IAsset EncodeToAdaptiveBitrateMP4Set(IAsset asset)
        {
            // Declare a new job.
            IJob job = _context.Jobs.Create("Media Encoder Standard Thumbnail Job");
            // Get a media processor reference, and pass to it the name of the 
            // processor to use for the specific task.
            IMediaProcessor processor = GetLatestMediaProcessorByName("Media Encoder Standard");

            // Load the XML (or JSON) from the local file.
            string configuration = File.ReadAllText("ThumbnailPreset_JSON.json");

            // Create a task
            ITask task = job.Tasks.AddNew("Media Encoder Standard Thumbnail task",
                    processor,
                    configuration,
                    TaskOptions.None);

            // Specify the input asset to be encoded.
            task.InputAssets.Add(asset);
            // Add an output asset to contain the results of the job. 
            // This output is specified as AssetCreationOptions.None, which 
            // means the output asset is not encrypted. 
            task.OutputAssets.AddNew("Output asset",
                    AssetCreationOptions.None);

            job.StateChanged += new EventHandler<JobStateChangedEventArgs>(JobStateChanged);
            job.Submit();
            job.GetExecutionProgressTask(CancellationToken.None).Wait();

            return job.OutputMediaAssets[0];
        }

        private static void JobStateChanged(object sender, JobStateChangedEventArgs e)
        {
            Console.WriteLine("Job state changed event:");
            Console.WriteLine("  Previous state: " + e.PreviousState);
            Console.WriteLine("  Current state: " + e.CurrentState);
            switch (e.CurrentState)
            {
                case JobState.Finished:
                    Console.WriteLine();
                    Console.WriteLine("Job is finished. Please wait while local tasks or downloads complete...");
                    break;
                case JobState.Canceling:
                case JobState.Queued:
                case JobState.Scheduled:
                case JobState.Processing:
                    Console.WriteLine("Please wait...\n");
                    break;
                case JobState.Canceled:
                case JobState.Error:

                    // Cast sender as a job.
                    IJob job = (IJob)sender;

                    // Display or log error details as needed.
                    break;
                default:
                    break;
            }
        }

        private static IMediaProcessor GetLatestMediaProcessorByName(string mediaProcessorName)
        {
            var processor = _context.MediaProcessors.Where(p => p.Name == mediaProcessorName).
            ToList().OrderBy(p => new Version(p.Version)).LastOrDefault();

            if (processor == null)
                throw new ArgumentException(string.Format("Unknown media processor", mediaProcessorName));

            return processor;
        }
    }
}

注意事项Considerations

请注意以下事项:The following considerations apply:

  • 为 Start/Step/Range 使用的显式时间戳假设输入源的长度至少为 1 分钟。The use of explicit timestamps for Start/Step/Range assumes that the input source is at least 1 minute long.

  • Jpg/Png/BmpImage 元素包含 Start、Step 和 Range 字符串属性 – 这些属性解释如下:Jpg/Png/BmpImage elements have Start, Step, and Range string attributes – these can be interpreted as:

    • 帧数(如果为非负整数),例如,"Start":"120";Frame Number if they are non-negative integers, for example "Start": "120",

    • 相对于源持续时间(如果以 % 为后缀表示),例如:"Start":"15%",或者Relative to source duration if expressed as %-suffixed, for example "Start": "15%", OR

    • 时间戳(如果以 HH:MM:SS...Timestamp if expressed as HH:MM:SS… 格式表示)。format. 例如,"Start" :"00:01:00"For example "Start" : "00:01:00"

      可以随意混搭使用表示法。You can mix and match notations as you please.

      此外,Start 还支持特殊的宏 {Best},它会尝试判断第一个“有意义”的内容帧。请注意:(Start 设置为 {Best} 时,将忽略 Step 与 Range)Additionally, Start also supports a special Macro:{Best}, which attempts to determine the first “interesting” frame of the content NOTE: (Step and Range are ignored when Start is set to {Best})

    • 默认值:Start:{Best}Defaults: Start:{Best}

  • 需要显式提供每个图像格式的输出格式:Jpg/Png/BmpFormat。Output format needs to be explicitly provided for each Image format: Jpg/Png/BmpFormat. 提供时,MES 会将 JpgVideo 与 JpgFormat 进行匹配,依此类推。When present, MES matches JpgVideo to JpgFormat and so on. OutputFormat 引入了新的图像编解码器特定宏 {Index},需要为图像输出格式提供该宏一次(且只需一次)。OutputFormat introduces a new image-codec specific Macro: {Index}, which needs to be present (once and only once) for image output formats.

后续步骤Next steps

可以在编码作业挂起时检查作业进度You can check the job progress while the encoding job is pending.

媒体服务学习路径Media Services learning paths

媒体服务 v3(最新版本)Media Services v3 (latest)

查看最新版本的 Azure 媒体服务!Check out the latest version of Azure Media Services!

媒体服务 v2(旧版)Media Services v2 (legacy)

另请参阅See Also

媒体服务编码概述Media Services Encoding Overview