Как получить звук для кодирования с помощью Xuggler

Пишу приложение, которое записывает экран и звук. Хотя запись экрана работает отлично, мне трудно получить необработанный звук с помощью библиотек JDK. Вот код:

try {
            // Now, we're going to loop
            long startTime = System.nanoTime();

            System.out.println("Encoding Image.....");
            while (!Thread.currentThread().isInterrupted()) {
                // take the screen shot
                BufferedImage screen = robot.createScreenCapture(screenBounds);


                // convert to the right image type
                BufferedImage bgrScreen = convertToType(screen,
                        BufferedImage.TYPE_3BYTE_BGR);

                // encode the image
                writer.encodeVideo(0, bgrScreen, System.nanoTime()
                        - startTime, TimeUnit.NANOSECONDS);

                /* Need to get audio here and then encode using xuggler. Something like 

                    WaveData wd = new WaveData();

                    TargetDataLine line;
                    AudioInputStream aus = new AudioInputStream(line);

                    short[] samples = getSourceSamples();
                       writer.encodeAudio(0, samples); */


                if (timeCreation < 10) {
                    timeCreation = getGMTTime();
                }
                // sleep for framerate milliseconds
                try {
                    Thread.sleep((long) (1000 / FRAME_RATE.getDouble()));
                } catch (Exception ex) {
                    System.err.println("stopping....");
                    break;
                }

            }
            // Finally we tell the writer to close and write the trailer if
            // needed
        } finally {
            writer.close();
        }

На этой странице есть псевдокод. нравиться

while(haveMoreAudio())
 {
   short[] samples = getSourceSamples();
   writer.encodeAudio(0, samples);
 }

но что именно я должен делать для getSourceSamples()?

Кроме того, бонусный вопрос - можно ли при таком подходе выбрать один из нескольких микрофонов?

См. Также: Кодирование и мультиплексирование Xuggler


person wrahool    schedule 05.02.2014    source источник


Ответы (1)


Попробуй это:

// Pick a format. Need 16 bits, the rest can be set to anything
// It is better to enumerate the formats that the system supports, because getLine() can error out with any particular format
AudioFormat audioFormat = new AudioFormat(44100.0F, 16, 2, true, false); 

// Get default TargetDataLine with that format
DataLine.Info dataLineInfo = new DataLine.Info( TargetDataLine.class, audioFormat );
TargetDataLine line = (TargetDataLine) AudioSystem.getLine(dataLineInfo);

// Open and start capturing audio    
line.open(audioFormat, line.getBufferSize());
line.start();

while (true) {
    // read as raw bytes
    byte[] audioBytes = new byte[ line.getBufferSize() / 2 ]; // best size?
    int numBytesRead = 0;
    numBytesRead =  line.read(audioBytes, 0, audioBytes.length);

    // convert to signed shorts representing samples
    int numSamplesRead = numBytesRead / 2;
    short[] audioSamples = new short[ numSamplesRead ];
    if (format.isBigEndian()) {
        for (int i = 0; i < numSamplesRead; i++) {
            audioSamples[i] = (short)((audioBytes[2*i] << 8) | audioBytes[2*i + 1]);
        }
    }
    else {
        for (int i = 0; i < numSamplesRead; i++) {
            audioSamples[i] = (short)((audioBytes[2*i + 1] << 8) | audioBytes[2*i]);
        }
    }

    // use audioSamples in Xuggler etc
}

Чтобы выбрать микрофон, вам, вероятно, придется сделать следующее:

Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
// Look through and select a mixer here, different mixers should be different inputs
int selectedMixerIndex = 0;
Mixer mixer = AudioSystem.getMixer(mixerInfo[ selectedMixerIndex ]);
TargetDataLine line = (TargetDataLine) mixer.getLine(dataLineInfo);

Я думаю, что возможно, что несколько микрофонов появятся в одном микшере как разные линии исходных данных. В этом случае вам придется открыть их и позвонить dataLine.getControl(FloatControl.Type.MASTER_GAIN).setValue( volume );, чтобы включить и выключить их.

См .: WaveData.java

Звуковая волна от TargetDataLine

Как установить громкость SourceDataLine в Java

person Alex I    schedule 05.02.2014
comment
Спасибо. Полагаю, format должно быть audioFormat? А что такое data? Кроме того, audioSamples[i] = audioBytes[2 * i] << 8 | (0xFF & audioBytes[2 * i + 1]); требуется приведение к short - person wrahool; 05.02.2014
comment
Спасибо. Но я получаю эту ошибку после нескольких предупреждений. Я видел их раньше и в предыдущих попытках. an error occurred: error Operation not permitted, failed to write trailer to /path/to/outputfile.mp4 - person wrahool; 05.02.2014
comment
@wrahool: эта ошибка не связана с чтением аудио. Я так понимаю, что сейчас работает аудиокод? Пожалуйста, не забудьте принять и проголосовать, а также задать еще один вопрос :) - person Alex I; 05.02.2014
comment
когда я отлаживаю код, я проверяю значения в массиве audioSamples, и все они равны -2. Я использую этот массив для кодирования звука, может быть, из-за этого ошибка? - person wrahool; 05.02.2014
comment
@wrahool: Сомневаюсь. Попробуйте установить audioSamples на все нули после чтения, но непосредственно перед кодированием, это не должно повлиять на ошибку. У меня есть представление об этой ошибке, но - пожалуйста, опубликуйте код, который вы используете для записи файла, в другом вопросе. - person Alex I; 05.02.2014
comment
@wrahool: Если audioSamples равно -2, что такое audioBytes? - person Alex I; 05.02.2014
comment
@wrahool: Во всяком случае, это довольно полный пример. Если вы хотите, чтобы я тоже его отлаживал, опубликуйте награду :) - person Alex I; 05.02.2014