亦身仙气 2025-05-08 18:14 采纳率: 68.6%
浏览 8
已结题

unity生成安卓应用的问题

#目前遇到的问题是,在安卓中播放视频流,并且监听视频流里面的声音大小,如果视频流里面有声音则通过计算音频数据来获取音量大小。
#但是目前遇到的问题是,在安卓中播放视频流的这个插件是,vlc for unity安卓版本的这个插件,他在安卓中播放声音是通过调用安卓代码播放的声音,不走unity内部的音频组件,这也导致我无法通过获取音频数据来获取视频流里面的声音大小,请问有什么方法能解决这个问题吗。
#我尝试拦截vlc for unity这个插件的声音,并且在unity中进行播放,不知道是我设置有问题还是哪里的问题,播放出来的声音和原本的声音是不一样的。
#我也尝试在调用安卓的代码,来录制他的声音,可是一直生成不了程序, 老是报错。

下面是java的代码,我想转换成jar或者是aar,但是转换出来的jar无法使用,导入到unity的时候一生成就报错。


// Assets/Plugins/Android/AudioCapturePlugin.java
package com.yourcompany.audiocapture;

import android.Manifest;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;

import androidx.annotation.RequiresPermission;

import com.unity3d.player.UnityPlayer;
import com.unity3d.player.UnityPlayerActivity;

public class AudioCapturePlugin extends UnityPlayerActivity {
    private static final String TAG = "AudioCapturePlugin";
    private static final int SAMPLE_RATE = 44100;
    private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
    private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(
            SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT);

    private AudioRecord audioRecord;
    private boolean isRecording = false;
    private Thread recordingThread;

    @RequiresPermission(Manifest.permission.RECORD_AUDIO)
    public void startRecording() {
        if (isRecording) return;

        audioRecord = new AudioRecord(
                MediaRecorder.AudioSource.VOICE_RECOGNITION, // 使用VOICE_RECOGNITION可以捕获程序自身声音(需要API 21+)
                SAMPLE_RATE,
                CHANNEL_CONFIG,
                AUDIO_FORMAT,
                BUFFER_SIZE);

        if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
            Log.e(TAG, "AudioRecord initialization failed");
            return;
        }

        audioRecord.startRecording();
        isRecording = true;

        recordingThread = new Thread(new Runnable() {
            @Override
            public void run() {
                short[] buffer = new short[BUFFER_SIZE / 2];
                while (isRecording) {
                    int read = audioRecord.read(buffer, 0, buffer.length);
                    if (read > 0) {
                        // 在这里处理音频数据
                        // 可以发送回Unity
                        UnityPlayer.UnitySendMessage("AudioManager", "OnAudioData", convertShortArrayToString(buffer, read));
                    }
                }
            }
        }, "AudioRecorder Thread");

        recordingThread.start();
    }

    public void stopRecording() {
        if (!isRecording) return;

        isRecording = false;
        try {
            recordingThread.join();
        } catch (InterruptedException e) {
            Log.e(TAG, "Interrupted while stopping recording", e);
        }

        audioRecord.stop();
        audioRecord.release();
        audioRecord = null;
    }

    private static String convertShortArrayToString(short[] array, int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(array[i]).append(",");
        }
        return sb.toString();
    }
}
  • 写回答

3条回答 默认 最新

  • 宝码香车 JavaScript领域优质创作者 2025-05-08 18:16
    关注

    让【宝码香车】来帮你解答,本回答参考DeepSeek编写,并整理提供。
    如果还有疑问可以点击头像关注私信或评论。如果答案让您满意,请采纳、点赞、关注,非常感谢!

    Unity中获取VLC插件音频数据的解决方案

    问题分析

    您遇到的核心问题是:VLC for Unity插件在安卓平台播放视频时,音频是通过原生Android API播放的,绕过了Unity的音频系统,导致无法通过Unity的标准方法获取音频数据。

    解决方案

    方案1:修改VLC插件源码直接获取音频数据(推荐)

    这是最直接的解决方案,但需要您有VLC插件的源码访问权限:

    1. 修改VLC插件源码,在音频数据发送到Android音频系统前获取副本
    2. 通过Unity的UnitySendMessage将音频数据发送回Unity

    方案2:使用AudioRecord捕获系统音频(需要API 21+)

    您尝试的AudioRecord方法理论上可行,但需要注意以下几点:

    1. 确保使用正确的AudioSource(VOICE_RECOGNITION需要API 21+)
    2. 需要正确处理权限和线程

    以下是修正后的代码:

    // Assets/Plugins/Android/AudioCapturePlugin.java
    package com.yourcompany.audiocapture;
    
    import android.Manifest;
    import android.media.AudioFormat;
    import android.media.AudioRecord;
    import android.media.MediaRecorder;
    import android.util.Log;
    import androidx.annotation.RequiresPermission;
    import com.unity3d.player.UnityPlayer;
    
    public class AudioCapturePlugin {
        private static final String TAG = "AudioCapturePlugin";
        private static final int SAMPLE_RATE = 44100;
        private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
        private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
        private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT);
    
        private AudioRecord audioRecord;
        private boolean isRecording = false;
        private Thread recordingThread;
    
        @RequiresPermission(Manifest.permission.RECORD_AUDIO)
        public void startRecording(String gameObjectName) {
            if (isRecording) return;
    
            try {
                audioRecord = new AudioRecord(
                        MediaRecorder.AudioSource.VOICE_RECOGNITION,
                        SAMPLE_RATE,
                        CHANNEL_CONFIG,
                        AUDIO_FORMAT,
                        BUFFER_SIZE);
    
                if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
                    Log.e(TAG, "AudioRecord initialization failed");
                    return;
                }
    
                audioRecord.startRecording();
                isRecording = true;
    
                recordingThread = new Thread(() -> {
                    short[] buffer = new short[BUFFER_SIZE / 2];
                    while (isRecording) {
                        int read = audioRecord.read(buffer, 0, buffer.length);
                        if (read > 0) {
                            float rms = calculateRMS(buffer, read);
                            UnityPlayer.UnitySendMessage(gameObjectName, "OnAudioLevel", String.valueOf(rms));
                        }
                    }
                }, "AudioRecorder Thread");
    
                recordingThread.start();
            } catch (Exception e) {
                Log.e(TAG, "Recording failed", e);
            }
        }
    
        public void stopRecording() {
            if (!isRecording) return;
    
            isRecording = false;
            try {
                recordingThread.join(1000);
            } catch (InterruptedException e) {
                Log.e(TAG, "Interrupted while stopping", e);
            }
    
            if (audioRecord != null) {
                audioRecord.stop();
                audioRecord.release();
                audioRecord = null;
            }
        }
    
        private float calculateRMS(short[] samples, int length) {
            float sum = 0;
            for (int i = 0; i < length; i++) {
                sum += samples[i] * samples[i];
            }
            return (float) Math.sqrt(sum / length);
        }
    }
    

    方案3:使用Unity Android插件桥接

    1. 创建Android库项目生成aar文件
    2. 在Unity中创建C#桥接脚本
    // Assets/Scripts/AudioCaptureBridge.cs
    using UnityEngine;
    
    public class AudioCaptureBridge : MonoBehaviour
    {
        private AndroidJavaObject audioCapturePlugin;
        
        void Start()
        {
            #if UNITY_ANDROID && !UNITY_EDITOR
            AndroidJavaClass pluginClass = new AndroidJavaClass("com.yourcompany.audiocapture.AudioCapturePlugin");
            audioCapturePlugin = pluginClass.CallStatic<AndroidJavaObject>("getInstance");
            #endif
        }
    
        public void StartRecording()
        {
            #if UNITY_ANDROID && !UNITY_EDITOR
            audioCapturePlugin.Call("startRecording", gameObject.name);
            #endif
        }
    
        public void StopRecording()
        {
            #if UNITY_ANDROID && !UNITY_EDITOR
            audioCapturePlugin.Call("stopRecording");
            #endif
        }
    
        // 从Android插件调用的方法
        public void OnAudioLevel(string levelStr)
        {
            float level = float.Parse(levelStr);
            // 处理音量数据
            Debug.Log("Current audio level: " + level);
        }
    }
    

    常见问题解决

    1. JAR/AAR生成问题

      • 确保使用Android Studio创建Android Library项目
      • 正确配置build.gradle文件
      • 生成aar文件而非jar
    2. 权限问题
      在AndroidManifest.xml中添加:

      <uses-permission android:name="android.permission.RECORD_AUDIO" />
      
    3. Unity导入问题

      • 确保aar文件放在Assets/Plugins/Android目录
      • 检查Unity的Player Settings中是否启用了自定义Main Gradle Template

    替代方案

    如果上述方法都不适用,可以考虑:

    1. 使用FFmpeg解码视频流并提取音频数据
    2. 寻找其他支持音频数据回调的Unity视频播放插件
    3. 联系VLC for Unity插件的开发者请求添加音频数据回调功能

    希望这些解决方案能帮助您解决问题!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 5月23日
  • 已采纳回答 5月15日
  • 创建了问题 5月8日