You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Node.js使用Azure Media Services转码生成HLS流的技术咨询

从AWS Elastic Transcoder迁移到Azure Media Services的方案

背景

原AWS架构通过Lambda触发Elastic Transcoder,将S3上传的视频转码为多画质HLS流。现已将S3替换为Azure Blob Storage,需基于Azure Media Services实现相同转码逻辑。


1. Node.js中使用Azure Media Services转码为HLS的示例

以下示例基于Azure Media Services v3 SDK(@azure/arm-mediaservices)实现,对应原AWS Lambda的转码逻辑:

前置准备

  • 安装依赖:npm install @azure/arm-mediaservices @azure/identity @azure/storage-blob dotenv
  • 配置环境变量:Azure订阅ID、资源组名、Media Services账户名、Blob存储连接字符串、存储账户名

代码示例

const { DefaultAzureCredential } = require("@azure/identity");
const { AzureMediaServices } = require("@azure/arm-mediaservices");
const { BlobServiceClient } = require("@azure/storage-blob");
const dotenv = require("dotenv");

dotenv.config();

// 初始化客户端
const credential = new DefaultAzureCredential();
const mediaServicesClient = new AzureMediaServices(
  credential,
  process.env.AZURE_SUBSCRIPTION_ID
);
const blobServiceClient = BlobServiceClient.fromConnectionString(
  process.env.AZURE_STORAGE_CONNECTION_STRING
);

// 核心转码函数
async function transcodeVideoToHLS(blobName, containerName) {
  const accountName = process.env.AZURE_MEDIA_SERVICES_ACCOUNT_NAME;
  const resourceGroupName = process.env.AZURE_RESOURCE_GROUP_NAME;
  
  // 1. 创建Media Services Asset(关联Blob存储中的源视频)
  const assetName = `input-asset-${Date.now()}`;
  const asset = await mediaServicesClient.assets.createOrUpdate(
    resourceGroupName,
    accountName,
    assetName,
    {
      description: "Input asset for video transcoding",
      storageAccountName: process.env.AZURE_STORAGE_ACCOUNT_NAME
    }
  );

  // 2. 将Blob中的视频复制到Asset对应的存储容器
  const sourceContainerClient = blobServiceClient.getContainerClient(containerName);
  const sourceBlobClient = sourceContainerClient.getBlobClient(blobName);
  const assetContainerClient = blobServiceClient.getContainerClient(asset.container);
  const destinationBlobClient = assetContainerClient.getBlobClient(blobName);
  await destinationBlobClient.syncCopyFromURL(sourceBlobClient.url);

  // 3. 创建或复用Transform(对应AWS Preset,定义转码规则)
  const transformName = "MultiBitrateHLS";
  try {
    await mediaServicesClient.transforms.get(resourceGroupName, accountName, transformName);
  } catch (err) {
    // 创建包含多画质HLS和MP4输出的Transform
    await mediaServicesClient.transforms.createOrUpdate(
      resourceGroupName,
      accountName,
      transformName,
      {
        description: "Multi-bitrate HLS + MP4 transcoding preset",
        outputs: [
          // HLS多码率自适应流(360p/480p/720p/1080p+64k音频)
          {
            preset: {
              "@odata.type": "#Microsoft.Media.StandardEncoderPreset",
              codecs: [
                {
                  "@odata.type": "#Microsoft.Media.H264Video",
                  keyFrameInterval: "PT2S",
                  complexity: "Balanced",
                  layers: [
                    { bitrate: 600000, width: "640", height: "360", label: "360p" },
                    { bitrate: 1500000, width: "854", height: "480", label: "480p" },
                    { bitrate: 3000000, width: "1280", height: "720", label: "720p" },
                    { bitrate: 6000000, width: "1920", height: "1080", label: "1080p" }
                  ]
                },
                {
                  "@odata.type": "#Microsoft.Media.AacAudio",
                  bitrate: 64000,
                  channels: 2
                }
              ],
              formats: [
                {
                  "@odata.type": "#Microsoft.Media.HlsFormat",
                  filenamePattern: "{Basename}_{Label}_{Bitrate}",
                  segmentsPerTsFile: 10 // 对应原SegmentDuration=10
                }
              ]
            }
          },
          // 额外MP4输出(对应原AWS的MP4 Preset)
          {
            preset: {
              "@odata.type": "#Microsoft.Media.StandardEncoderPreset",
              codecs: [
                {
                  "@odata.type": "#Microsoft.Media.H264Video",
                  keyFrameInterval: "PT2S",
                  complexity: "Balanced",
                  layers: [{ bitrate: 5000000, width: "1920", height: "1080" }]
                },
                {
                  "@odata.type": "#Microsoft.Media.AacAudio",
                  bitrate: 128000,
                  channels: 2
                }
              ],
              formats: [
                {
                  "@odata.type": "#Microsoft.Media.Mp4Format",
                  filenamePattern: "{Basename}_1080p.mp4"
                }
              ]
            }
          }
        ]
      }
    );
  }

  // 4. 创建转码Job
  const jobName = `transcode-job-${Date.now()}`;
  const outputAssetName = `output-asset-${Date.now()}`;
  await mediaServicesClient.jobs.create(
    resourceGroupName,
    accountName,
    transformName,
    jobName,
    {
      input: {
        "@odata.type": "#Microsoft.Media.JobInputAsset",
        assetName: assetName
      },
      outputs: [
        {
          "@odata.type": "#Microsoft.Media.JobOutputAsset",
          assetName: outputAssetName
        }
      ]
    }
  );

  console.log(`转码任务已启动:${jobName}`);
  console.log(`输出文件将存储在Asset:${outputAssetName}`);
}

// Azure Function触发器入口(监听Blob上传事件)
module.exports = async function (context, myBlob) {
  const blobName = context.bindingData.name;
  const containerName = context.bindingData.containerName;
  
  try {
    await transcodeVideoToHLS(blobName, containerName);
    context.done(null, "转码任务初始化成功");
  } catch (err) {
    context.log.error(err);
    context.done(err);
  }
};

2. 视频存储:Blob Storage还是Media Services Assets?

  • 核心结论:转码操作必须基于Media Services Assets,但源视频可先存储在Blob Storage,再关联到Assets;转码后的输出默认存储在Assets对应的Blob容器中,也可复制到其他Blob容器用于分发。
  • 详细说明:
    • Assets是Media Services的核心载体:Media Services的转码、流式处理等功能仅支持Assets作为输入输出,Assets本质是Blob Storage容器的逻辑封装,由Media Services管理权限和生命周期。
    • Blob Storage可作为源存储:用户上传的视频可直接存在Blob Storage中,无需迁移,只需将文件复制或关联到Media Services Asset即可触发转码。
    • 输出文件的处理:转码后的HLS流和MP4文件会自动保存到Output Asset对应的Blob容器,可直接通过Media Services流式终结点分发,也可复制到公共Blob容器配合CDN加速分发。

内容的提问来源于stack exchange,提问作者Ammar Abdul Aziz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 00:01:05