Blog de Raúl Salinas

Using the TV remote to control omxplayer on Raspberry Pi

I have a Raspberry Pi connected to my TV via HDMI. Despite having tried OpenELEC as a media center, I have other services running on that machine and I am just too console-oriented to select media through a graphical interface. I use a laptop to start films, but I was missing a way to pause or rewind playback. I finally solved it in a elegant way, using HDMI CEC.

HDMI is not just a standard for transferring video — it also supports control commands. For example, a TV can ask the player to pause using the TV's own remote, instead of needing a separate one. The RPi can also ask the TV to switch on and change to the relevant HDMI input. Fantastic.

The challenges:

  • Get the input from the remote. cec-client provides push/release events. On Raspbian: apt-get install cec-client.
  • Send commands to the running omxplayer. We use terminal mixer (tm), written by Lluís Batlle i Rossell. The idea is simple: run tm -wt omxplayer, then send commands from anywhere with echo -n COMMAND | tm -t. Install with ./configure && make && make install.

This script uses bash coprocesses, a beautiful feature of the shell:

#! /bin/bash -eu

# Launch a coprocessor that provides CEC input data.
# "pow 0" powers on the display at start. Then we wait for events.
# --line-buffered is essential for real-time response.
coproc cecclient { echo -e 'pow 0\nas'| cec-client |
    grep -e "key pressed" -e "key released" --line-buffered ; }

function cmd {
    # Start tm if not running yet
    [ ${tm_PID:-0} != 0 ] || coproc tm { tm -t;  }
    # Send command, ignore errors (common when omxplayer ends)
    echo -ne "$1" >&"${tm[1]}" || echo -e "Cannot send command\a"
}

# Read from the coprocessor's output
while read -u ${cecclient[0]} L
do
    echo $L    ## Debugging
    K=$(sed -n 's/.*key pressed: \([^ ]*\).*$/\1/p' <<< "$L" )
    R=$(sed -n 's/.*key released: \([^ ]*\).*$/\1/p' <<< "$L" )

    case $K in
    select|pause) cmd ' ' ;;
    backward|rewind) cmd '\e[D' ;;
    forward|Fast) cmd '\e[C' ;;
    up) cmd '+' ;;
    down) cmd '-' ;;
    left) cmd i ;;
    right) cmd o ;;
    F1) cmd 'n' ;;
    F2) cmd 'm' ;;
    F3) cmd 's' ;;
    F4) cmd 'k' ;;
    exit) sudo reboot ;;
    *) echo Unknown press: $K ;;
    esac

    case $R in
    stop) cmd q ;;
    *) echo Unknown release: $R ;;
    esac
done

Launching omxplayer

Modify the omxplayer wrapper script to prefix the omxplayer.bin invocation with tm -wt. Alternatively, always run tm -wt omxplayer ... or set up an alias.

Configuring the TV

Enable CEC on your TV (usually found in HDMI settings, sometimes called "Anynet+", "Bravia Sync", "SimpLink", etc.).

Future work

A nice improvement would be to launch cec-client only while omxplayer is running, saving processor time and avoiding interference with other CEC clients. The challenge is cleanly killing this script — including its two coprocesses — when omxplayer exits.