Mobile Development 8 min read

Extracting Audio from Android Devices Using MEmu Emulator and Python

This guide explains how to capture audio from Android applications by mapping MEmu emulator instances, automating screen recording with Windows APIs, and separating the audio track using ffmpeg, while addressing common pitfalls such as filename collisions and permission issues.

360 Quality & Efficiency
360 Quality & Efficiency
360 Quality & Efficiency
Extracting Audio from Android Devices Using MEmu Emulator and Python

In the 360 testing platform, extracting audio from video streams on Android devices is a difficult problem that requires a reliable method for capturing the sound generated by both third‑party and system apps.

Several approaches were evaluated: hardware‑supported audio routing (costly and unsuitable for third‑party APKs), rooting the device (high risk on real devices), using Android 9+ system recording (requires third‑party support and yields poor quality), recording the emulator’s output, capturing PC audio, and finally using the MEmu emulator’s own recording capabilities. The chosen solution is to use the MEmu emulator to record both video and audio.

Step 1 – Obtain Emulator Mapping : The MEmu installation directory contains .memu XML files (e.g., MEmu_1.memu ) that store each emulator’s name and ADB forwarding port. By parsing these XML files you can build a dictionary that maps the emulator index to its name and ADB port.

def parse_file(filepath):
    """Parse MEmu .memu XML files and return a dict of {index: [name, hostport]}"""
    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

Running memuc listvms --running on the command line provides the current emulator index, title, window handle, Android state, PID, and disk usage, which can be correlated with the parsed XML data.

memuc  listvms --running  # shows running emulator information

Step 2 – Start 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. Administrator privileges are required for the window‑manipulation calls to succeed.

win32gui.ShowWindow(hwnd, 1)  # show window
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)   # Ctrl up
win32api.keybd_event(116, 0, win32con.KEYEVENTF_KEYUP, 0)   # F5 up
# ... similar sequence with 117 (F6) to stop

Step 3 – Audio‑Video Separation : After recording, ffmpeg extracts the audio track from the generated .mp4 file and saves it as a .wav file.

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

Step 4 – Associate Video Files with Emulators : Several pitfalls were identified:

Video filenames are timestamped only to the second, causing possible collisions when multiple emulators record simultaneously.

There is no inherent mapping between a video file and the emulator that produced it.

User‑defined filenames may not match the emulator‑generated names, leading to missing‑file errors.

Solutions include inserting a delay of more than one second between recordings, recording the start time for each emulator, and using the timestamp to match video files to emulator instances.

Helper functions check for the existence of the video file and construct the corresponding .wav path:

if FileUtils.isExists(videopath):
    filepath_no_ext = os.path.splitext(videopath)[0]
    return filepath_no_ext + ".wav"
# additional logic for handling renamed or shifted files
PythonAndroidFFmpegScreen RecordingAudio ExtractionMEmu
360 Quality & Efficiency
Written by

360 Quality & Efficiency

360 Quality & Efficiency focuses on seamlessly integrating quality and efficiency in R&D, sharing 360’s internal best practices with industry peers to foster collaboration among Chinese enterprises and drive greater efficiency value.

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.