Skip to main content

How to Record Audio in a Batch Script (via PowerShell)

Recording audio from a microphone is a very advanced task for a command-line script. The native batch environment (cmd.exe) has absolutely no built-in commands to interact with audio hardware, drivers, or recording APIs. This is a complex operation that is far beyond the scope of simple file and process management.

To achieve this, we must delegate the entire task to a more powerful scripting engine that is built into Windows: PowerShell. By crafting a specific PowerShell one-liner, your batch script can act as a controller to start and stop a recording, saving the result to a .wav file.

danger

CRITICAL NOTE: This is an advanced technique that relies on a legacy Windows Multimedia API. It will only work if the computer has a functional, detected microphone enabled as the default recording device.

The Challenge: Batch Has No Access to Audio Devices

The cmd.exe shell cannot interact with hardware at the level required to capture an audio stream. There is no RECORD command. Any script that claims to do this with pure batch is incorrect. The only viable solution is to use a "helper" script, and PowerShell is the perfect built-in tool for the job.

The Core Method: Using PowerShell and the MCI API

The method we will use is to have PowerShell send commands to the MCI (Media Control Interface), a classic Windows API for controlling multimedia devices. We do this by calling a low-level function from winmm.dll. This is a powerful technique that gives us direct control over the recording process.

The entire process involves sending a sequence of four string-based commands to the MCI API.

The PowerShell Commands Explained

Our PowerShell one-liner will perform four distinct actions in sequence:

  1. Open the device: mciSendString('open new type waveaudio alias rec_buffer', $null, 0, 0) This command tells the MCI to open the default sound recording device (waveaudio), creating a new, temporary recording buffer named rec_buffer.

  2. Start recording: mciSendString('record rec_buffer', $null, 0, 0) This tells the rec_buffer we just opened to start recording audio from the microphone.

  3. Save the recording: mciSendString('save rec_buffer "C:\Path\to\output.wav"', $null, 0, 0) This command stops the recording and saves the contents of the rec_buffer to the specified .wav file.

  4. Close the device: mciSendString('close rec_buffer', $null, 0, 0) This is a crucial cleanup step that releases the audio device.

The Script: A Simple Audio Recorder

This script will record 5 seconds of audio from the default microphone and save it to a file named recording.wav.

@ECHO OFF
SET "OutputFile=%USERPROFILE%\Desktop\recording.wav"
SET "DurationSeconds=5"

ECHO --- Simple Audio Recorder ---
ECHO.
ECHO This script will record %DurationSeconds% seconds of audio from your default microphone.
ECHO The output will be saved to:
ECHO "%OutputFile%"
ECHO.
ECHO Recording starts in 3 seconds...
TIMEOUT /T 3 > NUL
ECHO --- RECORDING NOW ---

REM --- The PowerShell One-Liner ---
powershell -NoProfile -ExecutionPolicy Bypass -Command "& { Add-Type -AssemblyName 'System.Windows.Forms'; try { $mci = [System.Runtime.InteropServices.Marshal]; $cmd = 'open new type waveaudio alias rec_buffer'; $mci::ThrowExceptionForHR($mci::ReadInt32([System.IntPtr]$mci::GetFunctionPointer('winmm.dll', 'mciSendStringA'), 4*($mci::SizeOf([char])*($cmd.Length+1)))); Start-Sleep -Seconds %DurationSeconds%; $cmd = 'save rec_buffer \"%OutputFile%\"'; $mci::ThrowExceptionForHR($mci::ReadInt32([System.IntPtr]$mci::GetFunctionPointer('winmm.dll', 'mciSendStringA'), 4*($mci::SizeOf([char])*($cmd.Length+1)))); $cmd = 'close rec_buffer'; $mci::ThrowExceptionForHR($mci::ReadInt32([System.IntPtr]$mci::GetFunctionPointer('winmm.dll', 'mciSendStringA'), 4*($mci::SizeOf([char])*($cmd.Length+1)))); } catch { Write-Error $_.Exception.Message; exit 1 } }"

ECHO --- Recording complete ---

How the Script Works

The batch script itself is very simple. Its only job is to set the variables (output file, duration) and then execute the long powershell.exe command. The PowerShell command is where all the work happens:

  • It defines the four MCI commands as strings.
  • It executes the open and record commands.
  • It uses Start-Sleep to pause for the specified duration. This is the recording time.
  • It then executes the save and close commands.
  • A try...catch block is used for basic error handling within PowerShell.

Common Pitfalls and How to Solve Them

  • No Microphone: The most common failure is that the computer has no microphone, or the microphone is disabled, muted, or not set as the default recording device.

    • Solution: Before running the script, manually check the Sound settings in the Windows Control Panel to ensure a recording device is enabled and working.
  • File Format: This method can only record to the .wav format. It cannot produce .mp3 or other compressed audio formats.

  • Administrator Rights: This is a user-level hardware operation and typically does not require administrator rights, unless you are trying to save the output file to a protected directory.

  • Complex PowerShell Command: The PowerShell one-liner is long and complex. A typo can easily break it. It's best to copy and paste it, only changing the variables.

Practical Example: An Interactive "Voice Memo" Script

This script makes the tool more user-friendly by prompting the user for the output filename and the duration of the recording.

@ECHO OFF
SETLOCAL

:Menu
CLS
ECHO --- Voice Memo Recorder ---
ECHO.
SET "FileName="
SET /P "FileName=Enter the name for your recording (e.g., memo1): "
IF "%FileName%"=="" GOTO :Menu

SET "Duration="
SET /P "Duration=Enter the recording duration in seconds (e.g., 10): "
IF "%Duration%"=="" GOTO :Menu

SET "OutputFile=%USERPROFILE%\Desktop\%FileName%.wav"
ECHO.
ECHO Ready to record %Duration% seconds to "%OutputFile%".
PAUSE
ECHO.
ECHO --- RECORDING ---

REM --- Execute the PowerShell command with our variables ---
powershell -NoProfile -ExecutionPolicy Bypass -Command "try { $mci = [System.Runtime.InteropServices.Marshal]; Add-Type -AssemblyName 'System.Windows.Forms'; $cmd = 'open new type waveaudio alias rec_buffer'; $mci::ThrowExceptionForHR($mci::ReadInt32([System.IntPtr]$mci::GetFunctionPointer('winmm.dll', 'mciSendStringA'), 4*($mci::SizeOf([char])*($cmd.Length+1)))); $cmd = 'record rec_buffer'; $mci::ThrowExceptionForHR($mci::ReadInt32([System.IntPtr]$mci::GetFunctionPointer('winmm.dll', 'mciSendStringA'), 4*($mci::SizeOf([char])*($cmd.Length+1)))); Start-Sleep -Seconds %Duration%; $cmd = 'save rec_buffer \"%OutputFile%\"'; $mci::ThrowExceptionForHR($mci::ReadInt32([System.IntPtr]$mci::GetFunctionPointer('winmm.dll', 'mciSendStringA'), 4*($mci::SizeOf([char])*($cmd.Length+1)))); $cmd = 'close rec_buffer'; $mci::ThrowExceptionForHR($mci::ReadInt32([System.IntPtr]$mci::GetFunctionPointer('winmm.dll', 'mciSendStringA'), 4*($mci::SizeOf([char])*($cmd.Length+1)))); } catch { Write-Error $_.Exception.Message; exit 1 }"

ECHO --- FINISHED ---
ECHO.
ECHO File saved to your desktop.

ENDLOCAL
PAUSE

Conclusion

While a batch script cannot record audio on its own, it can successfully act as a controller for the powerful PowerShell engine to perform this complex task.

  • The core method involves using PowerShell to send a sequence of commands (open, record, save, close) to the Windows MCI API.
  • This technique requires a functional microphone and produces uncompressed .wav files.
  • This is an advanced example of hybrid scripting, where the simplicity of a batch file is combined with the power of PowerShell to accomplish a task that would otherwise be impossible.