Skip to main content

Records keypress events and converts them for replay on programmable USB HID devices

Project description

keystroke_transcriber: records your keystrokes and writes an Arduino sketch to replay the same keystrokes

If you need to write arduino sketches for USB HID keyboard emulation (Digispark, Teensy, Ducky USB), then this module might be useful to you.

This module records global keystroke events on your PC (when you tell it to), and uses the recorded keystroke sequence to write the sketch for you.

Simply tell it which programmable USB HID keyboard platform you’re using, and start pressing keys. keystroke_transcriber will generate a sketch file for you. You can even choose to maintain the timing between your original keypresses, if you want.

Limitations

Currently only supports Digispark: Support for Ducky USB and Teensy devices will be coming soon

Install

Install from pypi:

pip install keystroke_transcriber

keystroke_transcriber command-line arguments

usage: keystroke_transcriber [-h] [-p {oneshot,repeat-forever,repeat-n}]
                             [-t {digispark}] [-o OUTPUT_FILE]
                             [-n REPEAT_COUNT] [-D REPEAT_DELAY_MS]
                             [-d EVENT_DELAY_MS] [-m] [-r RECORD_SECONDS] [-s]
                             [-q]

Records global keypress events until Ctrl-C is pressed (or until a fixed time
has elapsed), and translates them into a program that replays those keypress
events on some programmable USB HID device (e.g. Digispark)

optional arguments:
  -h, --help            show this help message and exit
  -p {oneshot,repeat-forever,repeat-n}, --playback-type {oneshot,repeat-forever,repeat-n}
                        Set the playback style for recorded keystroke
                        sequences (default: oneshot)
  -t {digispark}, --target-type {digispark}
                        Set the type of programmable USB HID device to
                        generate output for (default: digispark)
  -o OUTPUT_FILE, --output-file OUTPUT_FILE
                        Write output to this file, instead of printing output
                        to the terminal (default: None)
  -n REPEAT_COUNT, --repeat-count REPEAT_COUNT
                        Sets how many times the recorded keystroke sequence
                        should be repeated (only used if --playback-type is
                        repeat-n) (default: 1)
  -D REPEAT_DELAY_MS, --repeat-delay-ms REPEAT_DELAY_MS
                        Sets delay between recorded keystroke sequence
                        repetitions, in milliseconds (only used if --playback-
                        type is repeat-n or repeat-forever) (default: 0)
  -d EVENT_DELAY_MS, --event-delay-ms EVENT_DELAY_MS
                        Sets delay between individual keystroke events, in
                        milliseconds (only used if --maintain-timing is False)
                        (default: 0)
  -m, --maintain-timing
                        Maintain timing between recorded keystrokes (default:
                        False)
  -r RECORD_SECONDS, --record-seconds RECORD_SECONDS
                        Record for this many seconds, instead of recording
                        until Ctrl-C is seen (default: None)
  -s, --translate-scan-codes
                        Attempt to translate PS/2 scan codes to USB HID usage
                        ID codes (default: True)
  -q, --quiet-keypresses
                        Don't print detected keypresses to the terminal
                        (default: False)

Example Digispark sketch generated by keystroke_transcriber

For this example, I ran keystroke_transcriber with the following arguments to record keypress events until Ctrl+C, and generate a sketch for Digispark devices:

python -m keystroke_transcriber -p oneshot -t digispark -m

Then, I performed the following keyboard / mouse actions:

  1. Typed Ctrl+R (to open the “run” program)

  2. Typed “notepad”, followed by the Enter key (to open the Notepad application)

  3. Typed “Hello, from keystroke_transcriber!!!!”

  4. Clicked on the terminal window in which I originally ran keystroke_transcriber, to bring it back into focus, so the Ctrl+C signal in the next step would be sent to the program, instead of being sent to notepad (This step will not be recorded/replicated by keystroke_transcriber, since keystroke_transcriber records keypresses and not mouse activity, but it is necessary to successfully record keystroke sequences so I am including it anyway)

  5. Typed Ctrl+C (to stop the recording)

After I pressed Ctrl+C, keystroke_transcriber provided the following Digispark sketch:

// Auto-generated by keystroke_transcriber. Do not modify!

#include "DigiKeyboard.h"

#define NUM_EVENTS (83u)

// Holds all information required to replay a single keypress
struct key_event
{
    uint8_t key;
    uint8_t mods;
    uint16_t delay_before_ms;
};

// Holds a sequence of one or more keypress events to be replayed
const struct key_event key_events[NUM_EVENTS] PROGMEM =
{
    {0, MOD_GUI_LEFT, 0u}, {21u, MOD_GUI_LEFT, 235u}, {0, MOD_GUI_LEFT, 95u},
    {0, 0, 47u}, {17u, 0, 284u}, {18u, 0, 46u}, {0, 0, 108u}, {23u, 0, 16u},
    {8u, 0, 79u}, {0, 0, 78u}, {19u, 0, 47u}, {0, 0, 94u}, {4u, 0, 61u},
    {7u, 0, 47u}, {0, 0, 93u}, {40u, 0, 188u}, {0, 0, 31u},
    {0, MOD_SHIFT_LEFT, 710u}, {11u, MOD_SHIFT_LEFT, 141u}, {0, 0, 143u},
    {8u, 0, 15u}, {0, 0, 63u}, {15u, 0, 15u}, {0, 0, 62u}, {15u, 0, 31u},
    {18u, 0, 47u}, {0, 0, 142u}, {54u, 0, 63u}, {44u, 0, 46u}, {0, 0, 78u},
    {9u, 0, 15u}, {0, 0, 94u}, {21u, 0, 78u}, {0, 0, 47u}, {18u, 0, 31u},
    {16u, 0, 78u}, {44u, 0, 94u}, {0, 0, 125u}, {14u, 0, 94u}, {0, 0, 48u},
    {8u, 0, 78u}, {0, 0, 31u}, {28u, 0, 62u}, {0, 0, 47u}, {22u, 0, 63u},
    {0, 0, 31u}, {23u, 0, 173u}, {21u, 0, 30u}, {0, 0, 95u}, {18u, 0, 62u},
    {14u, 0, 31u}, {0, 0, 79u}, {8u, 0, 30u}, {0, 0, 94u},
    {0, MOD_SHIFT_LEFT, 46u}, {45u, MOD_SHIFT_LEFT, 31u},
    {0, MOD_SHIFT_LEFT, 31u}, {0, 0, 62u}, {23u, 0, 141u}, {21u, 0, 61u},
    {4u, 0, 108u}, {0, 0, 140u}, {17u, 0, 15u}, {22u, 0, 31u}, {0, 0, 47u},
    {6u, 0, 111u}, {0, 0, 94u}, {21u, 0, 46u}, {0, 0, 47u}, {12u, 0, 31u},
    {5u, 0, 95u}, {0, 0, 139u}, {8u, 0, 46u}, {21u, 0, 47u}, {0, 0, 109u},
    {0, MOD_SHIFT_LEFT, 62u}, {30u, MOD_SHIFT_LEFT, 46u},
    {0, MOD_SHIFT_LEFT, 63u}, {30u, MOD_SHIFT_LEFT, 93u},
    {0, MOD_SHIFT_LEFT, 31u}, {30u, MOD_SHIFT_LEFT, 31u},
    {0, MOD_SHIFT_LEFT, 46u}, {0, 0, 15u}
};

// Send a single keypress event to the USB host
void send_key_event(const struct key_event *event)
{
    // millis() timestamp of the last sent event
    static unsigned long last_event_time_ms = 0u;

    unsigned long elapsed_ms = millis() - last_event_time_ms;

    if (event->delay_before_ms > elapsed_ms)
    {
    DigiKeyboard.delay(event->delay_before_ms - elapsed_ms);
}

last_event_time_ms = millis();
DigiKeyboard.sendKeyPress(event->key, event->mods);

}

// Replay all keypress events stored in PROGMEM
void replay_key_events()
{
    for (unsigned i = 0u; i < NUM_EVENTS; i++)
    {
        struct key_event event;

        event.key = pgm_read_byte_near(&key_events[i].key);
        event.mods = pgm_read_byte_near(&key_events[i].mods);
        event.delay_before_ms = pgm_read_word_near(&key_events[i].delay_before_ms);

        send_key_event(&event);
    }
}

void setup()
{
    replay_key_events();
}

void loop()
{

    DigiKeyboard.update();
}

If you flash this sketch on to your Digispark, and plug the Digispark into a Windows PC, you will see the keyboard activity I just described, complete with the timing of my original keypresses.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

keystroke_transcriber-1.0.1-py3-none-any.whl (17.1 kB view details)

Uploaded Python 3

File details

Details for the file keystroke_transcriber-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: keystroke_transcriber-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 17.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.50.2 CPython/3.7.6

File hashes

Hashes for keystroke_transcriber-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cd585efc0a461414ce5db977f27206ae05f3874446c6211e06ad4a1ab9761ed9
MD5 0d6893a0e3db158218afed6b5128dd4a
BLAKE2b-256 25f1360f88012a85e3d238ed552d6dc42732edd2ffc675d3e7b7131a5a742be8

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page