Background Image

Improving Touchscreen Control for MPV on Raspberry Pi

Feb
06

I’ve been working on a project involving a Raspberry Pi connected to a touchscreen, running an endless loop of video episodes with MPV media player. However, I ran into a few issues related to touchscreen input, MPV process management, and performance logging.

Python - Raspberry Pi

Introduction

I’ve been working on a project involving a Raspberry Pi connected to a touchscreen, running an endless loop of video episodes with MPV as the media player. However, I ran into a few issues related to touchscreen input, MPV process management, and performance logging. In this post, I’ll discuss the challenges I encountered and the improvements made to the system to get it running smoothly.


Challenges

1. Stacking Commands During Touch Events

One of the first challenges I faced was the stacking of commands triggered by multiple touch events. For example, if I triple-tapped the screen, I found that it would execute all three actions (play/pauseskip, and "move channel") instead of just the last one.

This was a result of the way touch events were being handled—every tap was immediately triggering an action. The system wasn’t able to distinguish between single, double, or triple taps, and as a result, multiple commands were being stacked.

2. Log File Issues

In addition to the command stacking issue, I noticed that some log messages weren’t appearing in the touchscreen.logfile as expected. Despite setting up logging with RotatingFileHandler, messages like "mpv heartbeat OK" weren’t being captured.

3. Performance Warnings from MPV

Another challenge was dealing with performance warnings from MPV, particularly regarding "dropped frames" and "unaligned available buffer size" messages in the log. While these were not directly impacting playback, they cluttered the log and led me to wonder whether they indicated a deeper performance issue.


Improvements Made

1. Preventing Command Stacking with Tap Debouncing

The first improvement we made was addressing the issue of command stacking. By introducing a debouncing mechanism, we were able to ensure that multiple taps within a short period were interpreted as a single command. Here’s how we tackled it:

  • Accumulating Taps:

Instead of immediately triggering a command with each tap, we accumulated the taps and waited for a pause in the input.

  • Using a Timer:

A timer was introduced that reset with each tap. Once the user stopped tapping for a specified interval (TRIPLE_TAP_INTERVAL), the appropriate command was executed based on the total number of taps. This approach ensured that only the final action (play/pause, skip, or channel switch) would be triggered, and the previous actions wouldn’t stack.

Updated Touch Handling Code:

click_in_progress = 0
tap_timer = None

def handle_taps():
    global click_in_progress
    if click_in_progress == 1:
        toggle_play_pause()
    elif click_in_progress == 2:
        skip_to_next()
    elif click_in_progress >= 3:
        play_longer_static_and_switch_playlist()
    click_in_progress = 0

def touch_control_loop():
    global click_in_progress, tap_timer
    device = InputDevice(device_path)
    print(f"Listening for touch events on device: {device_path}")

    for event in device.read_loop():
        if event.type == ecodes.EV_KEY and event.code == ecodes.BTN_TOUCH and event.value == 1:
            click_in_progress += 1
            if tap_timer is not None:
                tap_timer.cancel()
            tap_timer = threading.Timer(TRIPLE_TAP_INTERVAL, handle_taps)
            tap_timer.start()

This update ensures that the system reacts only once after a series of taps, preventing multiple actions from stacking.

2. Improving Logging to Capture Important Events

The second improvement focused on ensuring that all the relevant log messages were captured, particularly the ones related to MPV’s heartbeat and touch events.

Logging Configuration:

I realised that the logging configuration was missing from the code. To fix this, I added a logging setup using RotatingFileHandler, which allowed us to capture INFO and above messages in the log file. This solved the issue where "mpv heartbeat OK" and other relevant logs weren’t appearing.

Updated Logging Setup:

logger = logging.getLogger()
logger.setLevel(logging.INFO)

handler = RotatingFileHandler(LOG_FILE, maxBytes=MAX_LOG_SIZE, backupCount=3)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

Log Rotation and Size Management:

I also implemented log rotation using RotatingFileHandler, which ensured that the log file doesn’t grow too large. The log file size is capped at 3MB, and older logs are archived when the file exceeds this limit.

3. Addressing Performance Warnings from MPV

Finally, I addressed the MPV warnings about dropped frames and audio buffer alignment. While these weren’t causing any immediate issues with playback, I took the following steps to manage them:

Ignoring Non-Critical Logs:

I added the --msg-level=all=warn flag to MPV’s startup configuration, which reduced the verbosity of non-critical logs like dropped frames. This kept the log cleaner and focused on more important events.


Conclusion

In summary, I encountered several challenges with my touchscreen-controlled MPV setup on Raspberry Pi, from command stacking and missing logs to performance warnings. However, by implementing debouncing for touch events, improving the logging system, and addressing some environmental warnings, the system has become much more reliable and easier to monitor.

Key Takeaways:

  • Debouncing Touch Events: Prevent stacking of commands triggered by multiple taps in a short period.
  • Improving Logging: Set up proper logging configurations and file rotation to ensure logs capture relevant events.
  • MPV Performance Tuning: Adjust verbosity to focus on important performance metrics and reduce clutter.

Want to discuss this post?

While I haven't enabled comments to keep things simple and focused, I'm always open to hearing from readers!

If you'd like to discuss anything, feel free to email me at