How to Get Accurate Recording Duration from Unity's Microphone
This article is a translated version of my original post on Qiita. Original (Japanese): https://qiita.com/segur/items/6d7b140418ef9adf6e7c
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);
}
}
Explaining StartRecord
Starting the recording is straightforward — just call:
audioClip = Microphone.Start(mic, false, maxDuration, sampleRate);
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);
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);
This must be called before Microphone.End(mic). If called after, position will be 0.
Note: The original version of this code called
GetPositionafterEnd, which causedpositionto always be0. A reader pointed this out and I confirmed the fix — callingGetPositionbeforeEndreturns the correct value. The sample code has been updated accordingly. (Updated 2018/08/20)
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.