Mobile Development 8 min read

Extracting Audio from Android Emulators Using MEmu, Python, and FFmpeg

This guide explains how to capture internal audio from Android devices by running multiple MEmu emulators, parsing their configuration XML to map simulators to recordings, automating screen capture with Windows APIs, separating audio with FFmpeg, and addressing common pitfalls such as naming collisions and permission issues.

360 Tech Engineering
360 Tech Engineering
360 Tech Engineering
Extracting Audio from Android Emulators Using MEmu, Python, and FFmpeg

When testing audio‑video content on the 360 Open Test platform, extracting audio from Android devices becomes a challenge; the article first lists six possible approaches (hardware support, rooting, Android 9+ system recording, emulator internal recording, PC recording, and emulator self‑recording) and explains why using the MEmu emulator’s self‑recording feature is the most feasible.

Mapping Emulators to Recordings

The MEmu installation directory contains a MemuHyperv VMs folder with XML configuration files ( MEmu_*.memu ). By parsing these XML files, the script extracts each emulator’s name and its ADB hostport , building a dictionary that links emulator indices to their identifiers.

def parse_file(filepath):
    """
    Parse MEmu.memu xml file information, get info
    :param filepath:
    :return:
    """
    infodict = {}
    for root, dirs, files in os.walk(filepath):
        for f in files:
            if f.startswith("MEmu") and f.endswith(".memu"):
                path = os.path.join(root, f)
                dom = parse(path)
                data = dom.documentElement
                Machines = data.getElementsByTagName('Machine')
                for Machine in Machines:
                    Machine_name = Machine.getAttribute('name')
                    Machine_index = getMachineIndex(Machine_name)
                    break
                Forwardings = data.getElementsByTagName('Forwarding')
                for host in Forwardings:
                    if host.getAttribute('name') == "ADB":
                        hostport = host.getAttribute('hostport')
                        break
                infodict[Machine_index] = [Machine_name, hostport]
    return infodict

The command memuc listvms --running lists currently running emulators, providing index, title, window handle, Android status, PID, and disk usage, which can be merged with the previously built dictionary.

memuc  listvms --running # output: index, title, handle, Android?, pid, disk usage

Automating Screen Recording

Using the Windows API (win32gui, win32api, win32con), the script brings the target emulator window to the foreground and simulates Ctrl+F5 to start recording and Ctrl+F6 to stop it. The emulator must run with administrator privileges for the window‑focus operation to succeed.

win32gui.ShowWindow(hwnd, 1)  # bring window to front
win32gui.SetForegroundWindow(hwnd)
win32api.keybd_event(17, 0, 0, 0)   # Ctrl down
win32api.keybd_event(116, 0, 0, 0)   # F5 down (start)
win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)
win32api.keybd_event(116, 0, win32con.KEYEVENTF_KEYUP, 0)

# stop recording (Ctrl+F6)
win32api.keybd_event(17, 0, 0, 0)
win32api.keybd_event(117, 0, 0, 0)   # F6 down
win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)
win32api.keybd_event(117, 0, win32con.KEYEVENTF_KEYUP, 0)

Audio‑Video Separation

After recording, FFmpeg is used to extract the audio track from the video file, outputting a WAV file for further quality analysis.

ffmpeg -i video_path -ar 16000 -vn audio_output.wav

Common Pitfalls and Solutions

File‑name collisions: video files are named with timestamps down to seconds, which can cause overwrites. Solution: ensure at least a one‑second interval between recordings.

Missing mapping between video files and emulators: record the start time for each emulator before recording to correlate later.

Inconsistent file names between the emulator’s generated video and the expected name: allow a small time offset (≈1 s) and search for the file accordingly.

Finally, additional helper code checks for existing video files and derives the corresponding WAV file path, handling cases where the original MP4 may be missing.

if FileUtils.isExists(videopath):
    filepath_no_ext = os.path.splitext(videopath)[0]
    return filepath_no_ext + ".wav"
# ... additional logic for alternative naming patterns ...
PythonAndroidFFmpegemulatorAudio ExtractionMEmu
360 Tech Engineering
Written by

360 Tech Engineering

Official tech channel of 360, building the most professional technology aggregation platform for the brand.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.