From fa4b2286ed45545efeee41d10e7a5bac76811232 Mon Sep 17 00:00:00 2001
From: Dana <Dana_Lee1016@126.com>
Date: 星期三, 28 一月 2026 13:33:42 +0800
Subject: [PATCH] 1.usb 推流添加声音

---
 app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java |   57 +++++++++++++++++++
 app/src/main/java/com/safeluck/floatwindow/util/AudioRecordManager.java      |  123 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 180 insertions(+), 0 deletions(-)

diff --git a/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java b/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
index 97ba0b8..a43aef8 100644
--- a/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
+++ b/app/src/main/java/com/safeluck/floatwindow/manager/UsbCameraPushManager.java
@@ -7,6 +7,9 @@
 import android.view.SurfaceView;
 import android.view.WindowManager;
 
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
 import com.alivc.live.pusher.AlivcAudioAACProfileEnum;
 import timber.log.Timber;
 import com.alivc.live.pusher.AlivcEncodeModeEnum;
@@ -26,6 +29,7 @@
 import com.anyun.libusbcamera.UsbCamera;
 import com.safeluck.floatwindow.MediaArgu;
 import com.safeluck.floatwindow.ResponseVO;
+import com.safeluck.floatwindow.util.AudioRecordManager;
 
 /**
  * USB鎽勫儚澶存帹娴佺鐞嗗櫒
@@ -60,6 +64,9 @@
     
     // 棰勮 SurfaceView 鍜岄殣钘忕殑 Window
     private WindowManager windowManager;
+    
+    // 闊抽鎺ㄦ祦绾跨▼姹狅紙鍗曠嚎绋嬶級
+    private ExecutorService audioPushExecutor;
     
     /**
      * 鎺ㄦ祦鍥炶皟鎺ュ彛
@@ -132,6 +139,7 @@
     public void stopPush() {
         Timber.d("stopPush called");
         stopPushThread();
+        stopAudioTransfer();
         releaseAlivcPusher();
         if (usbCamera != null) {
             usbCamera.stopCamera();
@@ -293,6 +301,7 @@
             public void onPushStarted(AlivcLivePusher alivcLivePusher) {
                 Timber.d("onPushStarted");
                 pushStarted = true;
+                startAudioTransfer();
                 notifyCallback(1, 0, "鎺ㄦ祦宸插紑濮嬶紝鍒嗚鲸鐜�: " + resolutionArr[0] + "x" + resolutionArr[1]);
             }
             
@@ -624,4 +633,52 @@
             callback.onResult(response);
         }
     }
+
+
+    private void startAudioTransfer() {
+        Timber.i("寮�濮嬮�氳繃mic褰曞埗澹伴煶锛屼笂浼�");
+        
+        // 鍒涘缓鍗曠嚎绋嬬嚎绋嬫睜鐢ㄤ簬闊抽鎺ㄦ祦
+        if (audioPushExecutor == null || audioPushExecutor.isShutdown()) {
+            audioPushExecutor = Executors.newSingleThreadExecutor(r -> {
+                Thread thread = new Thread(r, "AudioPushThread");
+                thread.setDaemon(true);
+                return thread;
+            });
+        }
+        
+        AudioRecordManager.getInstance().startRecording((data, size) -> {
+            if (alivcPusher != null && audioPushExecutor != null && !audioPushExecutor.isShutdown()) {
+                // 鍦ㄥ崟绾跨▼绾跨▼姹犱腑鎵ц闊抽鎺ㄦ祦
+                audioPushExecutor.execute(() -> {
+                    try {
+                        alivcPusher.inputStreamAudioData(data, data.length, System.nanoTime() / 1000);
+                    } catch (Exception e) {
+                        Timber.e(e, "Error pushing audio data");
+                    }
+                });
+            }
+        });
+    }
+
+    private void stopAudioTransfer() {
+        Timber.i("鍋滄閫氳繃mic褰曞埗澹伴煶锛屼笂浼�");
+        AudioRecordManager.getInstance().stopRecording();
+        
+        // 鍋滄骞跺叧闂煶棰戞帹娴佺嚎绋嬫睜
+        if (audioPushExecutor != null && !audioPushExecutor.isShutdown()) {
+            audioPushExecutor.shutdown();
+            try {
+                // 绛夊緟鏈�澶�1绉掕浠诲姟瀹屾垚
+                if (!audioPushExecutor.awaitTermination(1, java.util.concurrent.TimeUnit.SECONDS)) {
+                    audioPushExecutor.shutdownNow();
+                }
+            } catch (InterruptedException e) {
+                audioPushExecutor.shutdownNow();
+                Thread.currentThread().interrupt();
+            }
+            audioPushExecutor = null;
+            Timber.d("闊抽鎺ㄦ祦绾跨▼姹犲凡鍏抽棴");
+        }
+    }
 }
diff --git a/app/src/main/java/com/safeluck/floatwindow/util/AudioRecordManager.java b/app/src/main/java/com/safeluck/floatwindow/util/AudioRecordManager.java
new file mode 100644
index 0000000..cff429c
--- /dev/null
+++ b/app/src/main/java/com/safeluck/floatwindow/util/AudioRecordManager.java
@@ -0,0 +1,123 @@
+package com.safeluck.floatwindow.util;
+
+
+import android.media.AudioFormat;
+import android.media.AudioRecord;
+import android.media.MediaRecorder;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * aaa
+ * Created by lzw on 2019/8/29. 11:19:57
+ * 閭锛�632393724@qq.com
+ * All Rights Saved! Chongqing AnYun Tech co. LTD
+ */
+public class AudioRecordManager {
+
+    private static final String TAG = "AudioRecordManager";
+    private static AudioRecordManager instance;
+
+    /***鏍囪鏄惁姝e湪褰曢煶**/
+    private boolean isRecording = false;
+
+    private AudioRecord audioRecord;
+    /***鏈�灏忕紦鍐插尯澶у皬*/
+    private int bufferSize = 0;
+    /***閲囨牱鐜�*/
+    private int sampleRateInHz = 32000;
+    /***閲忓寲浣嶆暟**/
+    private int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
+    /***瀛樻斁闊抽鏁版嵁鐨刡uffer**/
+    private byte[] buffer;
+
+    private int channelConf = AudioFormat.CHANNEL_IN_STEREO;
+    private OnAudioRecordListener onAudioRecordListener;
+
+
+    private AudioRecordManager() {
+        //璁$畻鏈�灏忕紦鍐插尯
+        bufferSize = AudioRecord.getMinBufferSize(sampleRateInHz, channelConf, audioFormat);
+//        bufferSize = bufferSize > 320 ? 320 : bufferSize;
+        Log.i(TAG,"mini buffersize="+bufferSize);
+
+        audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConf, audioFormat, bufferSize);
+    }
+
+
+    public static AudioRecordManager getInstance() {
+        if (instance == null) {
+            synchronized (AudioRecordManager.class) {
+                if (instance == null) {
+                    instance = new AudioRecordManager();
+                }
+            }
+        }
+        return instance;
+    }
+
+    /***
+     * 寮�濮嬮噰闆嗛煶棰�
+     */
+    public void startRecording(final OnAudioRecordListener onAudioRecordListener) {
+        setAudioRecordListener(onAudioRecordListener);
+        if (audioRecord == null){
+            audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRateInHz, channelConf, audioFormat, bufferSize);
+        }
+        buffer = new byte[bufferSize];
+
+                isRecording = true;
+                audioRecord.startRecording();
+                try {
+                    while (isRecording){
+                        int readSize = audioRecord.read(buffer,0,bufferSize);
+                        Log.i(TAG, "run: buffer length"+buffer.length+" readSize="+readSize);
+                        if (onAudioRecordListener != null){
+                            onAudioRecordListener.onVoiceRecord(buffer,bufferSize);
+                        }
+                    }
+                    audioRecord.stop();
+                    destroy();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+
+
+    }
+
+    /***
+     * 鍋滄闊抽閲囬泦
+     */
+    public void stopRecording(){
+        Log.i(TAG, "stopRecording");
+        isRecording = false;
+        setAudioRecordListener(null);
+    }
+
+    public void destroy(){
+        if (audioRecord!=null){
+            audioRecord.release();
+            audioRecord = null;
+        }
+
+    }
+
+    public interface OnAudioRecordListener {
+        /***
+         * 閲囬泦鍒扮殑闊抽淇℃伅鍥炶皟鍒颁笂灞�
+         * @param data
+         * @param size
+         */
+        void onVoiceRecord(byte[] data,int size);
+    }
+
+    private void setAudioRecordListener(OnAudioRecordListener onAudioRecordListener){
+        this.onAudioRecordListener = onAudioRecordListener;
+    }
+
+}

--
Gitblit v1.8.0