Streampunk / beamcoder

Node.js native bindings to FFmpeg.
GNU General Public License v3.0
392 stars 76 forks source link

Please create encode_aac.js example to show how to create AAC frames from raw PCM data. #84

Open metawrap-dev opened 2 years ago

metawrap-dev commented 2 years ago

I am trying to produce raw packets from RGB and PCM data.

Thanks to the encode_h264.js I can create video frames from RGB, but a simple example of how to produce AAC data is not available.

I have seen others here struggling with the same. What may seem simple and obvious to you is inscrutable to us mere mortals.

All the examples I have tried, most them are unstable (lots of crashes). The only data I get out does not seem to start with a recognisable AAC header.

eg.

frame_size 1024
2149cc803e1f000390757d5f41d7ec01fbd77cec013a3449d1a24e8d12746893a3449d1a24e8d12746893a3409d0a04e8502742813a1409cf9e4e7cf273e7939d389ce9c4e74d27366939b349cc984e64c272e5f6912224000092de4a1c800002474925300000908648850000cec0240080001208890c60000488524531231c91d00000000049092495125ac93180000000049ad24d71273c93e0000000003907437e0df81d7ec01fbd77cec0000007000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

The muxing examples produce mp4 files with silence.

Can you please provide a simple working example that could help a lot of us with a starting point to dynamic PCM -> AAC encoding?

metawrap-dev commented 2 years ago

I have some code like this to generate the raw audio frame data.

            const tone = new Float32Array(audioEncoder.frame_size);
            for (let s = 0; s < audioEncoder.frame_size; s++) {
                tone[s] = Math.sin(sample/10);
                sample++
            }

            const audioFrame = beamcoder.frame({
                dts: frame.dts,
                pts: frame.pts,            
                duration: audioSamplesPerFrame,
                sample_rate: audioEncParams.sampleRate,
                format: audioEncParams.sampleFormat,
                channel_layout: audioEncParams.channelLayout,
                data: [
                    tone,
                    tone,
                ],
            });

All I manage to get is crackling.

https://user-images.githubusercontent.com/42017256/151895156-630c896c-f0a2-4cef-954b-0cf32cb0c09b.mp4

Bahlinc-Dev commented 2 years ago

Sounds like the pts is not correct. Playing WAY to fast. The pts should advance relative to the sample rate. If you are encoding at say 16khz, then the encoder timebase should be set to 1/16000. This tells the encoder to expect 16000 individual samples per second. Since aac is 1024 samples per frame, you would need to inject 15.625 frames (of 1024 samples each) per second. PTS should advance by 1024 each time you write an audio frame, so that the pts is 16000 at the end of the first second. Same with video. if you are using standard MP4 timebase of 1/90000 then pts should equal 90000 at the end of the first second. Which means PTS advancement depends on frame rate. At 30fps video, each video frame PTS should advance by 3000. (because 90000/30 = 3000)

metawrap-dev commented 1 year ago

Some progress. The issue now is that I'm not sure if my the .data on an AAC packet is a complete AAC packet or does it also contain some beamcoder specific data?

I've tried appending all the AAC packets into a file but nothing seems to play it back.