@@ -50,21 +50,22 @@ export function extractFileConfig(file: MP4File, info: MP4Info) {
5050 const aTrack = info . audioTracks [ 0 ] ;
5151 if ( aTrack != null ) {
5252 const esdsBox = getESDSBoxFromMP4File ( file ) ;
53+ const audioInfo = esdsBox == null ? { } : parseAudioInfoFromESDSBox ( esdsBox ) ;
54+
5355 rs . audioTrackConf = {
5456 timescale : aTrack . timescale ,
55- samplerate : aTrack . audio . sample_rate ,
56- channel_count : aTrack . audio . channel_count ,
57+ samplerate : audioInfo . sampleRate ?? aTrack . audio . sample_rate ,
58+ channel_count : audioInfo . numberOfChannels ?? aTrack . audio . channel_count ,
5759 hdlr : 'soun' ,
5860 type : aTrack . codec . startsWith ( 'mp4a' ) ? 'mp4a' : aTrack . codec ,
59- description : getESDSBoxFromMP4File ( file ) ,
61+ description : esdsBox ,
6062 } ;
63+
6164 rs . audioDecoderConf = {
62- codec : aTrack . codec . startsWith ( 'mp4a' )
63- ? DEFAULT_AUDIO_CONF . codec
64- : aTrack . codec ,
65- numberOfChannels : aTrack . audio . channel_count ,
66- sampleRate : aTrack . audio . sample_rate ,
67- ...( esdsBox == null ? { } : parseAudioInfo4ESDSBox ( esdsBox ) ) ,
65+ codec : audioInfo . codec ?? DEFAULT_AUDIO_CONF . codec ,
66+ numberOfChannels :
67+ audioInfo . numberOfChannels ?? aTrack . audio . channel_count ,
68+ sampleRate : audioInfo . sampleRate ?? aTrack . audio . sample_rate ,
6869 } ;
6970 }
7071 return rs ;
@@ -97,12 +98,25 @@ function getESDSBoxFromMP4File(file: MP4File, codec = 'mp4a') {
9798 return mp4aBox ?. esds ;
9899}
99100
100- // 解决封装层音频信息标识错误,导致解码异常
101- function parseAudioInfo4ESDSBox ( esds : ESDSBoxParser ) {
102- const decoderConf = esds . esd . descs [ 0 ] ?. descs [ 0 ] ;
103- if ( decoderConf == null ) return { } ;
101+ // 从 ESDS Box 中解析出音频配置信息,解决封装层音频信息标识错误,导致解码异常
102+ function parseAudioInfoFromESDSBox ( esds : ESDSBoxParser ) : {
103+ codec ?: string ;
104+ sampleRate ?: number ;
105+ numberOfChannels ?: number ;
106+ } {
107+ let codec = 'mp4a' ;
108+ const decConfDesc = esds . esd . descs [ 0 ] ;
109+ if ( decConfDesc == null ) return { } ;
110+ codec += '.' + decConfDesc . oti . toString ( 16 ) ;
111+
112+ const decSpecInfo = decConfDesc . descs [ 0 ] ;
113+ if ( decSpecInfo == null ) return { codec } ;
104114
105- const [ byte1 , byte2 ] = decoderConf . data ;
115+ // ref: https://wiki.multimedia.cx/index.php/MPEG-4_Audio#Audio_Specific_Config
116+ const audioObjectType = ( decSpecInfo . data [ 0 ] & 0xf8 ) >> 3 ;
117+ codec += '.' + audioObjectType ;
118+
119+ const [ byte1 , byte2 ] = decSpecInfo . data ;
106120 // sampleRate 是第一字节后 3bit + 第二字节前 1bit
107121 const sampleRateIdx = ( ( byte1 & 0x07 ) << 1 ) + ( byte2 >> 7 ) ;
108122 // numberOfChannels 是第二字节 [2, 5] 4bit
@@ -111,7 +125,9 @@ function parseAudioInfo4ESDSBox(esds: ESDSBoxParser) {
111125 96000 , 88200 , 64000 , 48000 , 44100 , 32000 , 24000 , 22050 , 16000 , 12000 , 11025 ,
112126 8000 , 7350 ,
113127 ] as const ;
128+
114129 return {
130+ codec,
115131 sampleRate : sampleRateEnum [ sampleRateIdx ] ,
116132 numberOfChannels,
117133 } ;
0 commit comments