DEV Community

Shoichi Okaniwa
Shoichi Okaniwa

Posted on • Originally published at qiita.com

How to Get Accurate Recording Duration from Unity's Microphone

Introduction

I was building a voice recording feature using a smartphone microphone in Unity. The requirement was simple: tap a button to start recording, tap again to stop. However, I ran into a problem — I couldn't get the accurate recording duration. This article explains how I solved it.

Unity's Microphone Class

Unity provides a built-in Microphone class for recording audio.
Unity Documentation | Microphone

On iPhone, Android, and Mac, it uses the built-in microphone. On Windows, Unity will detect any connected microphone automatically (probably).

Sample Code (Updated: 2018/10/21)

I created a sample Unity project. Feel free to use it.
https://github.com/segurvita/UnityMicrophonePractice

It supports starting/stopping recording and playback via button controls.

Code Walkthrough

Here is the full sample code:

using UnityEngine;

public class RecordManager : MonoBehaviour
{
    // Public variables
    public int maxDuration;                  // Maximum recording duration (e.g., 20 seconds)
    public AudioClip audioClip;              // Audio data

    // Private variables
    private const int sampleRate = 16000;    // Recording sample rate
    private string mic;                      // Microphone device name

    ///-----------------------------------------------------------
    /// <summary>Start recording</summary>
    ///-----------------------------------------------------------
    public void StartRecord()
    {
        // Check if microphone exists
        if (Microphone.devices.Length == 0)
        {
            Debug.Log("No microphone found");
            return;
        }

        // Get microphone name
        mic = Microphone.devices[0];

        // Start recording; store audio data in audioClip
        audioClip = Microphone.Start(mic, false, maxDuration, sampleRate);
    }

    ///-----------------------------------------------------------
    /// <summary>Stop recording</summary>
    ///-----------------------------------------------------------
    public void StopRecord()
    {
        // Get the current recording position
        int position = Microphone.GetPosition(mic);

        // Force stop the microphone
        Microphone.End(mic);

        // Checking the duration shows maxDuration regardless of when we stopped — does it include silence?
        Debug.Log("Recording duration before fix: " + audioClip.length);

        // Allocate a temporary buffer and copy all audio data from audioClip
        float[] soundData = new float[audioClip.samples * audioClip.channels];
        audioClip.GetData(soundData, 0);

        // Create a new buffer sized exactly to the recorded position
        float[] newData = new float[position * audioClip.channels];

        // Copy only the recorded portion
        for (int i = 0; i < newData.Length; i++)
        {
            newData[i] = soundData[i];
        }

        // Create a new AudioClip instance and set the trimmed audio data
        AudioClip newClip = AudioClip.Create(audioClip.name, position, audioClip.channels, audioClip.frequency, false);
        newClip.SetData(newData, 0);

        // Replace the original audioClip with the new one
        AudioClip.Destroy(audioClip);
        audioClip = newClip;

        // Log the corrected duration
        Debug.Log("Recording duration after fix: " + newClip.length);
    }
}
Enter fullscreen mode Exit fullscreen mode

Explaining StartRecord

Starting the recording is straightforward — just call:

audioClip = Microphone.Start(mic, false, maxDuration, sampleRate);
Enter fullscreen mode Exit fullscreen mode

Without explicitly stopping, it will record for maxDuration seconds. The audio data is stored in audioClip, which is an instance of the AudioClip class — Unity's container for audio data. To play it back, pass audioClip to an AudioSource and call Play().

Explaining StopRecord

Stopping mid-recording is where things get complicated.

Calling:

Microphone.End(mic);
Enter fullscreen mode Exit fullscreen mode

stops the recording, but leaves audioClip in an unexpected state. Even if you stopped after 3 seconds, audioClip.length reports the full maxDuration — for example, 20 seconds.

It turns out audioClip.length is fixed to maxDuration the moment Microphone.Start() is called.

Since audioClip.length is read-only, I worked around this by reconstructing the AudioClip instance. I referenced this Q&A for the approach:
record dynamic length from microphone

If there's a cleaner way, I'd love to hear it.

Also, note this line:

int position = Microphone.GetPosition(mic);
Enter fullscreen mode Exit fullscreen mode

This must be called before Microphone.End(mic). If called after, position will be 0.

Summary

Unity's Microphone class makes it easy to record audio, but getting an accurate recording duration requires some extra work — specifically, reconstructing the AudioClip with the correct length after stopping.

Top comments (0)