FL Studio Python Scripting
Complete reference for FL Studio's Python API: MIDI controller scripting (14 modules, 427+ functions), piano roll note manipulation, Edison audio editing, and FLP file parsing with PyFLP.
Quick Start
Requirements
- FL Studio 20.8.4+, Python 3.6+
Check API Version
import general
print(f"API Version: {general.getVersion()}")
Script Installation
Place scripts in Shared\Python\User Scripts folder.
Three Scripting Contexts
1. MIDI Controller Scripting
Purpose: Control FL Studio through hardware MIDI controllers and send feedback to devices.
Runs: Continuously while FL Studio is open.
Available modules: transport, mixer, channels, arrangement, patterns, playlist, device, ui, general, plugins, screen, launchMapPages, utils, callbacks
Entry points:
def OnInit():
"""Called when script starts."""
pass
def OnDeInit():
"""Called when script stops."""
pass
def OnMidiMsg(msg):
"""Called for incoming MIDI messages."""
pass
def OnControlChange(msg):
"""Called for CC messages."""
pass
def OnNoteOn(msg):
"""Called for note-on messages."""
pass
def OnRefresh(flags):
"""Called when FL Studio state changes."""
pass
2. Piano Roll Scripting
Purpose: Manipulate notes and markers in the piano roll editor.
Runs: Once when user invokes through Scripts menu.
Available modules: flpianoroll, enveditor
import flpianoroll
score = flpianoroll.score
for note in score.notes:
note.velocity = 0.8 # Set all velocities to 80%
3. Edison Audio Scripting
Purpose: Edit and process audio samples in Edison.
Runs: Once within Edison's context.
Available modules: enveditor
API Module Reference Map
Navigate to the appropriate reference file based on what you need to control.
Read these files ONLY when you need specific API signatures.
Core Workflow Modules
| Module |
Functions |
What It Controls |
Reference |
| transport |
20 |
Play, stop, record, position, tempo, looping |
api-transport.md |
| mixer |
69 |
Track volume/pan/mute/solo, EQ, routing, effects |
api-mixer.md |
| channels |
48 |
Channel rack, grid bits, step sequencer, notes |
api-channels.md |
Arrangement Modules
| Module |
Functions |
What It Controls |
Reference |
| arrangement + patterns |
9 + 25 |
Markers, time, pattern control, groups |
api-arrangement-patterns.md |
| playlist |
41 |
Playlist tracks, live mode, performance, blocks |
api-playlist.md |
Device & Communication
| Module |
Functions |
What It Controls |
Reference |
| device |
34 |
MIDI I/O, sysex, dispatch, hardware refresh |
api-device.md |
UI & Application Control
| Module |
Functions |
What It Controls |
Reference |
| ui + general |
71 + 24 |
Windows, navigation, undo/redo, version, snap |
api-ui-general.md |
Plugins
| Module |
Functions |
What It Controls |
Reference |
| plugins |
13 |
Plugin parameters, presets, names, colors |
api-plugins.md |
Specialized Hardware Display
| Module |
Functions |
What It Controls |
Reference |
| screen + launchMapPages |
9 + 12 |
AKAI Fire screen, launchpad page management |
api-screen-launchmap.md |
Utilities, Constants & MIDI Reference
| Module |
Functions |
What It Controls |
Reference |
| utils + constants |
21 |
Color conversion, math, note names, MIDI tables |
api-utils-constants.md |
Callbacks & FlMidiMsg
| Module |
Functions |
What It Controls |
Reference |
| callbacks |
26 |
All callback functions, FlMidiMsg class, event flow |
api-callbacks.md |
Non-MIDI Scripting APIs
Piano Roll & Edison
Note, Marker, ScriptDialog, score classes for piano roll manipulation plus Edison enveditor utilities.
See piano-roll-edison.md
FLP File Parsing (PyFLP)
External library for reading/writing .flp project files without FL Studio running. Batch processing, analysis, automated generation.
See pyflp.md
Common Patterns
Minimal MIDI Controller Skeleton
# name=My Controller
# url=https://example.com
import device
import mixer
import transport
def OnInit():
if device.isAssigned():
print(f"Connected: {device.getName()}")
def OnDeInit():
print("Script shut down")
def OnControlChange(msg):
if msg.data1 == 7: # Volume CC
mixer.setTrackVolume(mixer.trackNumber(), msg.data2 / 127.0)
msg.handled = True
def OnNoteOn(msg):
track = msg.data1 % 8
mixer.setActiveTrack(track)
msg.handled = True
def OnRefresh(flags):
pass # Update hardware display here
Key Pattern: Always Check Device Assignment
def OnInit():
if not device.isAssigned():
print("No output device linked!")
return
# Safe to use device.midiOutMsg() etc.
Key Pattern: Mark Events as Handled
def OnControlChange(msg):
if msg.data1 == 7:
mixer.setTrackVolume(0, msg.data2 / 127.0)
msg.handled = True # Prevent FL Studio from also processing this
Key Pattern: Send Feedback to Hardware
def OnRefresh(flags):
if device.isAssigned():
# Update volume fader LED
vol = int(mixer.getTrackVolume(0) * 127)
device.midiOutMsg(0xB0, 0, 7, vol)
For complete examples (MIDI learn, scale enforcer, LED feedback, batch quantization, sysex handling, performance monitoring, automation engine, debugging):
See examples-patterns.md
Best Practices
Performance
- Cache module references at top level (import once)
- Avoid tight loops in MIDI callbacks (keep under 10ms)
- Batch UI updates; use
device.directFeedback() for controller echo
Hardware Integration
- Always check
device.isAssigned() before device functions
- Implement two-way sync for all controls (send feedback on state change)
- Test on real hardware (virtual ports behave differently)
Code Organization
- Separate MIDI mapping from business logic (use a controller class)
- Keep callbacks responsive; offload complex work
- Handle edge cases: invalid indices, missing devices, out-of-range values
Troubleshooting
Script Not Receiving MIDI
- Check
device.isAssigned() returns True
- Verify MIDI input port in FL Studio MIDI Settings
- Ensure callback functions are defined at module level (not nested)
- Check MIDI message status bytes match expected values
Piano Roll Script Not Working
- Verify script is in
Shared\Python\User Scripts folder
- Ensure a pattern is open in piano roll before running
- Access notes via
flpianoroll.score.notes
Performance Issues
- Avoid complex calculations inside
OnIdle() (called every ~20ms)
- Don't repeatedly query values that haven't changed
- Use
device.setHasMeters() only if peak meters are needed
FAQ
- Double-click detection: Use
device.isDoubleClick(index)
- Inter-script communication: Use
device.dispatch(ctrlIndex, message)
- LED control:
device.midiOutMsg(0x90, 0, note, velocity) for note-on LEDs
- processMIDICC vs OnControlChange: Use
On* callbacks for modern code
- GUI access: Limited through
ui module; full UI automation not available
- Multiple devices: Check
device.getName() to identify, handle per-port
Resources
1---2name: flstudio-scripting3description: FL Studio Python scripting for MIDI controller development, piano roll manipulation, Edison audio editing, workflow automation, and FLP file parsing with PyFLP. Use for programmatic configuration, device customization, MIDI transport, macros, and save file manipulation. Covers all 427+ API functions across 14 MIDI scripting modules plus piano roll, Edison, and PyFLP contexts.4---56# FL Studio Python Scripting78Complete reference for FL Studio's Python API: MIDI controller scripting (14 modules, 427+ functions), piano roll note manipulation, Edison audio editing, and FLP file parsing with PyFLP.910## Quick Start1112### Requirements13- FL Studio 20.8.4+, Python 3.6+1415### Check API Version16```python17import general18print(f"API Version: {general.getVersion()}")19```2021### Script Installation22Place scripts in `Shared\Python\User Scripts` folder.2324---2526## Three Scripting Contexts2728### 1. MIDI Controller Scripting2930**Purpose:** Control FL Studio through hardware MIDI controllers and send feedback to devices.31**Runs:** Continuously while FL Studio is open.32**Available modules:** transport, mixer, channels, arrangement, patterns, playlist, device, ui, general, plugins, screen, launchMapPages, utils, callbacks3334**Entry points:**35```python36def OnInit():37 """Called when script starts."""38 pass3940def OnDeInit():41 """Called when script stops."""42 pass4344def OnMidiMsg(msg):45 """Called for incoming MIDI messages."""46 pass4748def OnControlChange(msg):49 """Called for CC messages."""50 pass5152def OnNoteOn(msg):53 """Called for note-on messages."""54 pass5556def OnRefresh(flags):57 """Called when FL Studio state changes."""58 pass59```6061### 2. Piano Roll Scripting6263**Purpose:** Manipulate notes and markers in the piano roll editor.64**Runs:** Once when user invokes through Scripts menu.65**Available modules:** `flpianoroll`, `enveditor`6667```python68import flpianoroll69score = flpianoroll.score70for note in score.notes:71 note.velocity = 0.8 # Set all velocities to 80%72```7374### 3. Edison Audio Scripting7576**Purpose:** Edit and process audio samples in Edison.77**Runs:** Once within Edison's context.78**Available modules:** `enveditor`7980---8182## API Module Reference Map8384Navigate to the appropriate reference file based on what you need to control.85Read these files ONLY when you need specific API signatures.8687### Core Workflow Modules8889| Module | Functions | What It Controls | Reference |90|--------|-----------|-----------------|-----------|91| **transport** | 20 | Play, stop, record, position, tempo, looping | [api-transport.md](references/api-transport.md) |92| **mixer** | 69 | Track volume/pan/mute/solo, EQ, routing, effects | [api-mixer.md](references/api-mixer.md) |93| **channels** | 48 | Channel rack, grid bits, step sequencer, notes | [api-channels.md](references/api-channels.md) |9495### Arrangement Modules9697| Module | Functions | What It Controls | Reference |98|--------|-----------|-----------------|-----------|99| **arrangement** + **patterns** | 9 + 25 | Markers, time, pattern control, groups | [api-arrangement-patterns.md](references/api-arrangement-patterns.md) |100| **playlist** | 41 | Playlist tracks, live mode, performance, blocks | [api-playlist.md](references/api-playlist.md) |101102### Device & Communication103104| Module | Functions | What It Controls | Reference |105|--------|-----------|-----------------|-----------|106| **device** | 34 | MIDI I/O, sysex, dispatch, hardware refresh | [api-device.md](references/api-device.md) |107108### UI & Application Control109110| Module | Functions | What It Controls | Reference |111|--------|-----------|-----------------|-----------|112| **ui** + **general** | 71 + 24 | Windows, navigation, undo/redo, version, snap | [api-ui-general.md](references/api-ui-general.md) |113114### Plugins115116| Module | Functions | What It Controls | Reference |117|--------|-----------|-----------------|-----------|118| **plugins** | 13 | Plugin parameters, presets, names, colors | [api-plugins.md](references/api-plugins.md) |119120### Specialized Hardware Display121122| Module | Functions | What It Controls | Reference |123|--------|-----------|-----------------|-----------|124| **screen** + **launchMapPages** | 9 + 12 | AKAI Fire screen, launchpad page management | [api-screen-launchmap.md](references/api-screen-launchmap.md) |125126### Utilities, Constants & MIDI Reference127128| Module | Functions | What It Controls | Reference |129|--------|-----------|-----------------|-----------|130| **utils** + constants | 21 | Color conversion, math, note names, MIDI tables | [api-utils-constants.md](references/api-utils-constants.md) |131132### Callbacks & FlMidiMsg133134| Module | Functions | What It Controls | Reference |135|--------|-----------|-----------------|-----------|136| **callbacks** | 26 | All callback functions, FlMidiMsg class, event flow | [api-callbacks.md](references/api-callbacks.md) |137138---139140## Non-MIDI Scripting APIs141142### Piano Roll & Edison143Note, Marker, ScriptDialog, score classes for piano roll manipulation plus Edison enveditor utilities.144See [piano-roll-edison.md](references/piano-roll-edison.md)145146### FLP File Parsing (PyFLP)147External library for reading/writing .flp project files without FL Studio running. Batch processing, analysis, automated generation.148See [pyflp.md](references/pyflp.md)149150---151152## Common Patterns153154### Minimal MIDI Controller Skeleton155156```python157# name=My Controller158# url=https://example.com159160import device161import mixer162import transport163164def OnInit():165 if device.isAssigned():166 print(f"Connected: {device.getName()}")167168def OnDeInit():169 print("Script shut down")170171def OnControlChange(msg):172 if msg.data1 == 7: # Volume CC173 mixer.setTrackVolume(mixer.trackNumber(), msg.data2 / 127.0)174 msg.handled = True175176def OnNoteOn(msg):177 track = msg.data1 % 8178 mixer.setActiveTrack(track)179 msg.handled = True180181def OnRefresh(flags):182 pass # Update hardware display here183```184185### Key Pattern: Always Check Device Assignment186187```python188def OnInit():189 if not device.isAssigned():190 print("No output device linked!")191 return192 # Safe to use device.midiOutMsg() etc.193```194195### Key Pattern: Mark Events as Handled196197```python198def OnControlChange(msg):199 if msg.data1 == 7:200 mixer.setTrackVolume(0, msg.data2 / 127.0)201 msg.handled = True # Prevent FL Studio from also processing this202```203204### Key Pattern: Send Feedback to Hardware205206```python207def OnRefresh(flags):208 if device.isAssigned():209 # Update volume fader LED210 vol = int(mixer.getTrackVolume(0) * 127)211 device.midiOutMsg(0xB0, 0, 7, vol)212```213214For complete examples (MIDI learn, scale enforcer, LED feedback, batch quantization, sysex handling, performance monitoring, automation engine, debugging):215See [examples-patterns.md](references/examples-patterns.md)216217---218219## Best Practices220221### Performance2221. Cache module references at top level (import once)2232. Avoid tight loops in MIDI callbacks (keep under 10ms)2243. Batch UI updates; use `device.directFeedback()` for controller echo225226### Hardware Integration2271. Always check `device.isAssigned()` before device functions2282. Implement two-way sync for all controls (send feedback on state change)2293. Test on real hardware (virtual ports behave differently)230231### Code Organization2321. Separate MIDI mapping from business logic (use a controller class)2332. Keep callbacks responsive; offload complex work2343. Handle edge cases: invalid indices, missing devices, out-of-range values235236---237238## Troubleshooting239240### Script Not Receiving MIDI2411. Check `device.isAssigned()` returns `True`2422. Verify MIDI input port in FL Studio MIDI Settings2433. Ensure callback functions are defined at module level (not nested)2444. Check MIDI message status bytes match expected values245246### Piano Roll Script Not Working2471. Verify script is in `Shared\Python\User Scripts` folder2482. Ensure a pattern is open in piano roll before running2493. Access notes via `flpianoroll.score.notes`250251### Performance Issues2521. Avoid complex calculations inside `OnIdle()` (called every ~20ms)2532. Don't repeatedly query values that haven't changed2543. Use `device.setHasMeters()` only if peak meters are needed255256---257258## FAQ259260- **Double-click detection:** Use `device.isDoubleClick(index)`261- **Inter-script communication:** Use `device.dispatch(ctrlIndex, message)`262- **LED control:** `device.midiOutMsg(0x90, 0, note, velocity)` for note-on LEDs263- **processMIDICC vs OnControlChange:** Use `On*` callbacks for modern code264- **GUI access:** Limited through `ui` module; full UI automation not available265- **Multiple devices:** Check `device.getName()` to identify, handle per-port266267---268269## Resources270271- **Official FL Studio API:** https://www.image-line.com/fl-studio/modules/python-scripting/272- **PyFLP GitHub:** https://github.com/demberto/PyFLP273- **API Functions:** 427+ across 14 modules | **Last Updated:** 2025