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

AWS MediaConvert转码HLS无音频问题排查求助

HLS转码后无音频问题的排查与解决

问题背景

使用AWS MediaConvert将视频转码为DASH和HLS格式,DASH输出音视频播放正常,但HLS输出仅能播放视频、无音频。S3存储桶的输出目录中已生成.aac音频文件、.ts视频文件及.m3u8清单文件。

相关代码与配置

MediaConvert服务类代码(Python)

class MediaConvertService:
    aws_region = settings.AWS_REGION_NAME
    role_arn = settings.MEDIA_CONVERT_ROLE_ARN
    job_template = settings.MEDIA_CONVERT_JOB_TEMPLATE

    @classmethod
    def get_client(cls):
        return boto3.client("mediaconvert", region_name=cls.aws_region)

    @classmethod
    def prepare_media_convert_job_settings(cls, s3_url, bucket_name, object_key):
        job_settings = {
            "Role": cls.role_arn,
            "JobTemplate": cls.job_template,
            "Settings": {
                "Inputs": [
                    {
                        "FileInput": s3_url,
                        "VideoSelector": {
                            "ColorSpace": "FOLLOW",
                        },
                        "AudioSelectors": {
                            "Audio Selector 1": {"DefaultSelection": "DEFAULT"}
                        },
                        "TimecodeSource": "ZEROBASED",
                    }
                ],
                "OutputGroups": [
                    {
                        "CustomName": "CF-AEMC-GRP",
                        "Name": "DASH ISO",
                        "OutputGroupSettings": {
                            "Type": "DASH_ISO_GROUP_SETTINGS",
                            "DashIsoGroupSettings": {
                                "Destination": f"s3://{bucket_name}/output/DASH/{object_key}/",
                                "FragmentLength": 2,
                                "SegmentLength": 30,
                                "AudioChannelConfigSchemeIdUri": "MPEG_CHANNEL_CONFIGURATION"
                            }
                        },
                        "Outputs": [
                            {
                                "ContainerSettings": {"Container": "MPD"},
                                "VideoDescription": {
                                    "CodecSettings": {
                                        "Codec": "H_264",
                                        "H264Settings": {
                                            "MaxBitrate": 20000000,
                                            "RateControlMode": "QVBR",
                                            "SceneChangeDetect": "TRANSITION_DETECTION",
                                            "QvbrSettings": {
                                                "QvbrQualityLevel": 7
                                            }
                                        }
                                    }
                                },
                                "NameModifier": "_dash_video"
                            },
                            {
                                "ContainerSettings": {"Container": "MPD"},
                                "AudioDescriptions": [
                                    {
                                        "CodecSettings": {
                                            "Codec": "AAC",
                                            "AacSettings": {
                                                "Bitrate": 96000,
                                                "CodingMode": "CODING_MODE_2_0",
                                                "SampleRate": 48000
                                            }
                                        }
                                    }
                                ],
                                "NameModifier": "_dash_audio"
                            }
                        ]
                    },
                    {
                        "CustomName": "CF-AEMC-GRP-HLS",
                        "Name": "Apple HLS",
                        "OutputGroupSettings": {
                            "Type": "HLS_GROUP_SETTINGS",
                            "HlsGroupSettings": {
                                "Destination": f"s3://{bucket_name}/output/HLS/{object_key}/",
                                "SegmentLength": 6,
                                "MinSegmentLength": 2,
                                "OutputSelection": "MANIFESTS_AND_SEGMENTS",
                                "DirectoryStructure": "SINGLE_DIRECTORY",
                                "ManifestCompression": "NONE",
                                "StreamInfResolution": "INCLUDE"
                            }
                        },
                        "Outputs": [
                            {
                                "ContainerSettings": {"Container": "M3U8"},
                                "VideoDescription": {
                                    "CodecSettings": {
                                        "Codec": "H_264",
                                        "H264Settings": {
                                            "MaxBitrate": 20000000,
                                            "RateControlMode": "QVBR",
                                            "SceneChangeDetect": "TRANSITION_DETECTION",
                                            "QvbrSettings": {
                                                "QvbrQualityLevel": 7
                                            }
                                        }
                                    }
                                },
                                "NameModifier": "_hls_video"
                            },
                            {
                                "ContainerSettings": {"Container": "M3U8"},
                                "AudioDescriptions": [
                                    {
                                        "AudioSourceName": "Audio Selector 1",
                                        "CodecSettings": {
                                            "Codec": "AAC",
                                            "AacSettings": {
                                                "Bitrate": 96000,
                                                "CodingMode": "CODING_MODE_2_0",
                                                "SampleRate": 48000
                                            }
                                        }
                                    }
                                ],
                                "NameModifier": "_hls_audio"
                            }
                        ]
                    }
                ]
            },
        }
        return job_settings

    @classmethod
    def create_job(cls, s3_url, bucket_name, object_key):
        job_settings = cls.prepare_media_convert_job_settings(
            s3_url=s3_url, bucket_name=bucket_name, object_key=object_key
        )
        mediaconvert_client = cls.get_client()
        response = mediaconvert_client.create_job(**job_settings)
        assert response.get("ResponseMetadata", {}).get("HTTPStatusCode") == 201
        # remove extension from object key
        key = object_key.split(".")[0]
        dash_url = settings.DASH_FILE_PATH.format(
            bucket_name=bucket_name,
            region=cls.aws_region,
            content_dir=f"DASH/{object_key}",
            dash_file_name=key,
        )
        hls_url = settings.HLS_FILE_PATH.format(
            bucket_name=bucket_name,
            region=cls.aws_region,
            content_dir=f"HLS/{object_key}",
            hls_file_name=key,
        )
        return dash_url, hls_url

作业模板JSON

{
  "Description": "DASH ISO media convert for videos",
  "Category": "video",
  "Name": " Prod AEMC Template",
  "Settings": {
    "TimecodeConfig": {
      "Source": "ZEROBASED"
    },
    "OutputGroups": [
      {
        "CustomName": "CF-AEMC-GRP",
        "Name": "DASH ISO",
        "Outputs": [
          {
            "ContainerSettings": {
              "Container": "MPD"
            },
            "VideoDescription": {
              "CodecSettings": {
                "Codec": "H_264",
                "H264Settings": {
                  "MaxBitrate": 10000000,
                  "RateControlMode": "QVBR",
                  "SceneChangeDetect": "TRANSITION_DETECTION"
                }
              }
            },
            "NameModifier": "_dash_video"
          },
          {
            "ContainerSettings": {
              "Container": "MPD"
            },
            "AudioDescriptions": [
              {
                "AudioSourceName": "Audio Selector 1",
                "CodecSettings": {
                  "Codec": "AAC",
                  "AacSettings": {
                    "Bitrate": 96000,
                    "CodingMode": "CODING_MODE_2_0",
                    "SampleRate": 48000
                  }
                }
              }
            ],
            "NameModifier": "_dash_audio"
          }
        ],
        "OutputGroupSettings": {
          "Type": "DASH_ISO_GROUP_SETTINGS",
          "DashIsoGroupSettings": {
            "AudioChannelConfigSchemeIdUri": "MPEG_CHANNEL_CONFIGURATION",
            "SegmentLength": 30,
            "Destination": "s3://content/output/DASH/",
            "DestinationSettings": {
              "S3Settings": {
                "StorageClass": "STANDARD"
              }
            },
            "FragmentLength": 2
          }
        }
      },
      {
        "CustomName": "CF-AEMC-GRP-HLS",
        "Name": "Apple HLS",
        "Outputs": [
          {
            "ContainerSettings": {
              "Container": "M3U8",
              "M3u8Settings": {}
            },
            "VideoDescription": {
              "CodecSettings": {
                "Codec": "H_264",
                "H264Settings": {
                  "MaxBitrate": 20000000,
                  "RateControlMode": "QVBR",
                  "SceneChangeDetect": "TRANSITION_DETECTION"
                }
              }
            },
            "OutputSettings": {
              "HlsSettings": {}
            },
            "NameModifier": "_hls_video"
          },
          {
            "ContainerSettings": {
              "Container": "M3U8",
              "M3u8Settings": {}
            },
            "AudioDescriptions": [
              {
                "AudioSourceName": "Audio Selector 1",
                "CodecSettings": {
                  "Codec": "AAC",
                  "AacSettings": {
                    "Bitrate": 96000,
                    "CodingMode": "CODING_MODE_2_0",
                    "SampleRate": 48000
                  }
                }
              }
            ],
            "OutputSettings": {
              "HlsSettings": {}
            },
            "NameModifier": "_hls_audio"
          }
        ],
        "OutputGroupSettings": {
          "Type": "HLS_GROUP_SETTINGS",
          "HlsGroupSettings": {
            "SegmentLength": 10,
            "Destination": "s3://content/output/HLS/",
            "DestinationSettings": {
              "S3Settings": {
                "StorageClass": "STANDARD"
              }
            },
            "MinSegmentLength": 0
          }
        }
      }
    ],
    "Inputs": [
      {
        "AudioSelectors": {
          "Audio Selector 1": {
            "DefaultSelection": "DEFAULT"
          }
        },
        "VideoSelector": {
          "ColorSpace": "FOLLOW"
        },
        "TimecodeSource": "ZEROBASED"
      }
    ]
  },
  "AccelerationSettings": {
    "Mode": "DISABLED"
  },
  "StatusUpdateInterval": "SECONDS_60",
  "Priority": 0,
  "HopDestinations": []
}

生成的清单文件

根清单文件

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=1128250,AVERAGE-BANDWIDTH=537898,CODECS="avc1.640029",RESOLUTION=640x360,FRAME-RATE=24.000
Padmaavat_Official_Trailer_Ranveer_Singh_Shahid_Kapoor_Deepika_Padukone_hls_video.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=96510,AVERAGE-BANDWIDTH=96210,CODECS="mp4a.40.2"
Padmaavat_Official_Trailer_Ranveer_Singh_Shahid_Kapoor_Deepika_Padukone_hls_audio.m3u8

音频清单文件(截取)

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:7
#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:6,
Padmaavat_Official_Trailer_Ranveer_Singh_Shahid_Kapoor_Deepika_Padukone_hls_audio_00001.aac
#EXTINF:6,
Padmaavat_Official_Trailer_Ranveer_Singh_Shahid_Kapoor_Deepika_Padukone_hls_audio_00002.aac
#EXTINF:6,
#EXT-X-ENDLIST

问题解答

1. HLS输出配置是否存在缺失项?

是的,核心问题是HLS清单的音频流关联配置缺失:

  • 当前根清单把音频作为独立的#EXT-X-STREAM-INF流存在,但多数HLS播放器不会自动加载独立音频流,需要通过#EXT-X-MEDIA标签声明音频轨,并在视频流的#EXT-X-STREAM-INF中用AUDIO属性关联。
  • MediaConvert的HLS音频Output中HlsSettings为空,未设置音频标识信息(如名称、语言),导致生成的清单没有正确的关联标签。
  • 当前配置把音频当成了单独的流轨道,不符合HLS多轨合并的规范,应该将音频配置为音频Rendition而非独立自适应流。

2. 确保HLS流正确合并音视频轨道的步骤

步骤1:修改MediaConvert的HLS输出配置

在HLS OutputGroup的音频Output中添加HlsSettings配置,指定音频标识:

# 音频Output的修改内容
{
    "ContainerSettings": {
        "Container": "M3U8",
        "M3u8Settings": {
            "AudioRenditionSets": "AUDIO"  # 声明为音频轨集合
        }
    },
    "AudioDescriptions": [
        {
            "AudioSourceName": "Audio Selector 1",
            "CodecSettings": {
                "Codec": "AAC",
                "AacSettings": {
                    "Bitrate": 96000,
                    "CodingMode": "CODING_MODE_2_0",
                    "SampleRate": 48000
                }
            },
            "LanguageCode": "eng",
            "LanguageDescription": "English"
        }
    ],
    "OutputSettings": {
        "HlsSettings": {
            "AudioOnlyContainer": "AUTOMATIC",
            "Name": "audio_main"  # 音频轨命名,用于关联
        }
    },
    "NameModifier": "_hls_audio"
}

同时在视频Output的HlsSettings中添加关联配置:

# 视频Output的修改内容
{
    "ContainerSettings": {"Container": "M3U8"},
    "VideoDescription": {
        # 原视频编码配置不变
    },
    "OutputSettings": {
        "HlsSettings": {
            "AudioRenditionSets": "AUDIO"  # 关联音频轨集合
        }
    },
    "NameModifier": "_hls_video"
}

步骤2:调整HlsGroupSettings配置

在HlsGroupSettings中补充以下配置:

"HlsGroupSettings": {
    "Destination": f"s3://{bucket_name}/output/HLS/{object_key}/",
    "SegmentLength": 6,
    "MinSegmentLength": 2,
    "OutputSelection": "MANIFESTS_AND_SEGMENTS",
    "DirectoryStructure": "SINGLE_DIRECTORY",
    "ManifestCompression": "NONE",
    "StreamInfResolution": "INCLUDE",
    "ManifestDurationFormat": "FLOATING_POINT",
    "AudioOnlyStream": "ALLOWED"
}

步骤3:验证生成的根清单

修改后生成的根清单应包含#EXT-X-MEDIA标签,并在视频流的STREAM-INF中关联音频:

#EXTM3U
#EXT-X-VERSION:4
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="AUDIO",NAME="English",LANGUAGE="eng",DEFAULT=YES,AUTOSELECT=YES,URI="xxx_hls_audio.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=1128250,AVERAGE-BANDWIDTH=537898,CODECS="avc1.640029,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=24.000,AUDIO="AUDIO"
xxx_hls_video.m3u8

这样播放器就能识别视频流关联的音频轨,自动加载播放。

步骤4:测试播放

使用标准HLS播放器(如Safari、hls.js)播放修改后的根清单,确认音视频同步播放。


内容的提问来源于stack exchange,提问作者Abinash Biswal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 22:39:50