# 如何获得音频比特率

#### 问题现象

如何获得多个音频轨道里每一个音频轨的比特率。

#### 背景知识

*   AVMetadataExtractor可以实现从原始媒体资源中获取元数据AVMetadata。其中AVMetadata.tracks为媒体资源的轨道信息。
*   AVPlayer用于实现端到端播放原始媒体资源。AVPlayer.getTrackDescription用于获得音视频媒体资源的轨道信息。
*   媒体资源的轨道信息使用MediaDescription表示，通过key-value方式获取媒体信息。MediaDescriptionKey.MD\_KEY\_TRACK\_TYPE表示轨道类型，MediaDescriptionKey.MD\_KEY\_BITRATE表示比特率。

#### 解决方案

方案一：使用AVMetadataExtractor调用fetchMetadata接口获得元数据AVMetadata。通过AVMetadata.tracks属性获得媒体资源的轨道信息，遍历轨道信息，从音频轨信息中获得对应比特率。

```
try {
  let avMetadataExtractor: media.AVMetadataExtractor = await media.createAVMetadataExtractor();
  let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  avMetadataExtractor.fdSrc = await context.resourceManager.getRawFd('video.mp4');
  let metadata: media.AVMetadata = await avMetadataExtractor.fetchMetadata();
  if (metadata.tracks) {
    for (const track of metadata.tracks) {
      if (track[media.MediaDescriptionKey.MD_KEY_TRACK_TYPE] === media.MediaType.MEDIA_TYPE_AUD) {
        let trackIdx: number = track[media.MediaDescriptionKey.MD_KEY_TRACK_INDEX] as number;
        let bitrate: number = track[media.MediaDescriptionKey.MD_KEY_BITRATE] as number;
        console.info(`Audio Track ${trackIdx} bitrate is ${bitrate}`);
      }
    }
  }
  await avMetadataExtractor.release();
} catch (error) {
  console.error(`failed to get audio bitrate by AVMetadataExtractor: ${JSON.stringify(error)}`);
}
```

方案二：使用AVPlayer在prepared/playing/paused状态下调用getTrackDescription接口获得音视频的轨道信息，遍历轨道信息，从音频轨信息中获得对应比特率。

```
try {
  let avPlayer: media.AVPlayer = await media.createAVPlayer();
  avPlayer.on('stateChange', async (state: media.AVPlayerState) => {
    switch (state) {
      case 'initialized':
        await avPlayer.prepare();
        break;
      case 'prepared':
        let tracks: Array<media.MediaDescription> = await avPlayer.getTrackDescription();
        for (const track of tracks) {
          if (track[media.MediaDescriptionKey.MD_KEY_TRACK_TYPE] === media.MediaType.MEDIA_TYPE_AUD) {
            let trackIdx: number = track[media.MediaDescriptionKey.MD_KEY_TRACK_INDEX] as number;
            let bitrate: number = track[media.MediaDescriptionKey.MD_KEY_BITRATE] as number;
            console.info(`Audio Track ${trackIdx} bitrate is ${bitrate}`);
          }
        }
        await avPlayer.release();
        break;
      case 'error':
        await avPlayer.release();
        break;
    }
  });
  let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
  avPlayer.fdSrc = await context.resourceManager.getRawFd('video.mp4');
} catch (error) {
  console.error(`failed to get audio bitrate by AVMetadataExtractor: ${JSON.stringify(error)}`);
}
```

完成参考代码如下：

```
import { media } from '@kit.MediaKit';
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct Index {
  build() {
    Column({ space: 20 }) {
      Button('AVMetadataExtractor')
        .padding(5)
        .fontSize(30)
        .onClick(async () => {
          try {
            let avMetadataExtractor: media.AVMetadataExtractor = await media.createAVMetadataExtractor();
            let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
            avMetadataExtractor.fdSrc = await context.resourceManager.getRawFd('video.mp4');
            let metadata: media.AVMetadata = await avMetadataExtractor.fetchMetadata();
            if (metadata.tracks) {
              for (const track of metadata.tracks) {
                if (track[media.MediaDescriptionKey.MD_KEY_TRACK_TYPE] === media.MediaType.MEDIA_TYPE_AUD) {
                  let trackIdx: number = track[media.MediaDescriptionKey.MD_KEY_TRACK_INDEX] as number;
                  let bitrate: number = track[media.MediaDescriptionKey.MD_KEY_BITRATE] as number;
                  console.info(`Audio Track ${trackIdx} bitrate is ${bitrate}`);
                }
              }
            }
            await avMetadataExtractor.release();
          } catch (error) {
            console.error(`failed to get audio bitrate by AVMetadataExtractor: ${JSON.stringify(error)}`);
          }
        });

      Button('AVPlayer')
        .padding(5)
        .fontSize(30)
        .onClick(async () => {
          try {
            let avPlayer: media.AVPlayer = await media.createAVPlayer();
            avPlayer.on('stateChange', async (state: media.AVPlayerState) => {
              switch (state) {
                case 'initialized':
                  await avPlayer.prepare();
                  break;
                case 'prepared':
                  let tracks: Array<media.MediaDescription> = await avPlayer.getTrackDescription();
                  for (const track of tracks) {
                    if (track[media.MediaDescriptionKey.MD_KEY_TRACK_TYPE] === media.MediaType.MEDIA_TYPE_AUD) {
                      let trackIdx: number = track[media.MediaDescriptionKey.MD_KEY_TRACK_INDEX] as number;
                      let bitrate: number = track[media.MediaDescriptionKey.MD_KEY_BITRATE] as number;
                      console.info(`Audio Track ${trackIdx} bitrate is ${bitrate}`);
                    }
                  }
                  await avPlayer.release();
                  break;
                case 'error':
                  await avPlayer.release();
                  break;
              }
            });
            let context: Context = this.getUIContext().getHostContext() as common.UIAbilityContext;
            avPlayer.fdSrc = await context.resourceManager.getRawFd('video.mp4');
          } catch (error) {
            console.error(`failed to get audio bitrate by AVMetadataExtractor: ${JSON.stringify(error)}`);
          }
        });
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center);
  }
}
```