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---5
6# FL Studio Python Scripting
7
8Complete 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.
9
10## Quick Start
11
12### Requirements
13- FL Studio 20.8.4+, Python 3.6+
14
15### Check API Version
16```python
17import general
18print(f"API Version: {general.getVersion()}")
19```
20
21### Script Installation
22Place scripts in `Shared\Python\User Scripts` folder.
23
24---
25
26## Three Scripting Contexts
27
28### 1. MIDI Controller Scripting
29
30**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, callbacks
33
34**Entry points:**
35```python
36def OnInit():
37 """Called when script starts."""
38 pass
39
40def OnDeInit():
41 """Called when script stops."""
42 pass
43
44def OnMidiMsg(msg):
45 """Called for incoming MIDI messages."""
46 pass
47
48def OnControlChange(msg):
49 """Called for CC messages."""
50 pass
51
52def OnNoteOn(msg):
53 """Called for note-on messages."""
54 pass
55
56def OnRefresh(flags):
57 """Called when FL Studio state changes."""
58 pass
59```
60
61### 2. Piano Roll Scripting
62
63**Purpose:** Manipulate notes and markers in the piano roll editor.
64**Runs:** Once when user invokes through Scripts menu.
65**Available modules:** `flpianoroll`, `enveditor`
66
67```python
68import flpianoroll
69score = flpianoroll.score
70for note in score.notes:
71 note.velocity = 0.8 # Set all velocities to 80%
72```
73
74### 3. Edison Audio Scripting
75
76**Purpose:** Edit and process audio samples in Edison.
77**Runs:** Once within Edison's context.
78**Available modules:** `enveditor`
79
80---
81
82## API Module Reference Map
83
84Navigate to the appropriate reference file based on what you need to control.
85Read these files ONLY when you need specific API signatures.
86
87### Core Workflow Modules
88
89| 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) |
94
95### Arrangement Modules
96
97| 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) |
101
102### Device & Communication
103
104| Module | Functions | What It Controls | Reference |
105|--------|-----------|-----------------|-----------|
106| **device** | 34 | MIDI I/O, sysex, dispatch, hardware refresh | [api-device.md](references/api-device.md) |
107
108### UI & Application Control
109
110| 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) |
113
114### Plugins
115
116| Module | Functions | What It Controls | Reference |
117|--------|-----------|-----------------|-----------|
118| **plugins** | 13 | Plugin parameters, presets, names, colors | [api-plugins.md](references/api-plugins.md) |
119
120### Specialized Hardware Display
121
122| 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) |
125
126### Utilities, Constants & MIDI Reference
127
128| 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) |
131
132### Callbacks & FlMidiMsg
133
134| Module | Functions | What It Controls | Reference |
135|--------|-----------|-----------------|-----------|
136| **callbacks** | 26 | All callback functions, FlMidiMsg class, event flow | [api-callbacks.md](references/api-callbacks.md) |
137
138---
139
140## Non-MIDI Scripting APIs
141
142### Piano Roll & Edison
143Note, Marker, ScriptDialog, score classes for piano roll manipulation plus Edison enveditor utilities.
144See [piano-roll-edison.md](references/piano-roll-edison.md)
145
146### 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)
149
150---
151
152## Common Patterns
153
154### Minimal MIDI Controller Skeleton
155
156```python
157# name=My Controller
158# url=https://example.com
159
160import device
161import mixer
162import transport
163
164def OnInit():
165 if device.isAssigned():
166 print(f"Connected: {device.getName()}")
167
168def OnDeInit():
169 print("Script shut down")
170
171def OnControlChange(msg):
172 if msg.data1 == 7: # Volume CC
173 mixer.setTrackVolume(mixer.trackNumber(), msg.data2 / 127.0)
174 msg.handled = True
175
176def OnNoteOn(msg):
177 track = msg.data1 % 8
178 mixer.setActiveTrack(track)
179 msg.handled = True
180
181def OnRefresh(flags):
182 pass # Update hardware display here
183```
184
185### Key Pattern: Always Check Device Assignment
186
187```python
188def OnInit():
189 if not device.isAssigned():
190 print("No output device linked!")
191 return
192 # Safe to use device.midiOutMsg() etc.
193```
194
195### Key Pattern: Mark Events as Handled
196
197```python
198def 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 this
202```
203
204### Key Pattern: Send Feedback to Hardware
205
206```python
207def OnRefresh(flags):
208 if device.isAssigned():
209 # Update volume fader LED
210 vol = int(mixer.getTrackVolume(0) * 127)
211 device.midiOutMsg(0xB0, 0, 7, vol)
212```
213
214For 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)
216
217---
218
219## Best Practices
220
221### Performance
2221. 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 echo
225
226### Hardware Integration
2271. Always check `device.isAssigned()` before device functions
2282. Implement two-way sync for all controls (send feedback on state change)
2293. Test on real hardware (virtual ports behave differently)
230
231### Code Organization
2321. Separate MIDI mapping from business logic (use a controller class)
2332. Keep callbacks responsive; offload complex work
2343. Handle edge cases: invalid indices, missing devices, out-of-range values
235
236---
237
238## Troubleshooting
239
240### Script Not Receiving MIDI
2411. Check `device.isAssigned()` returns `True`
2422. Verify MIDI input port in FL Studio MIDI Settings
2433. Ensure callback functions are defined at module level (not nested)
2444. Check MIDI message status bytes match expected values
245
246### Piano Roll Script Not Working
2471. Verify script is in `Shared\Python\User Scripts` folder
2482. Ensure a pattern is open in piano roll before running
2493. Access notes via `flpianoroll.score.notes`
250
251### Performance Issues
2521. Avoid complex calculations inside `OnIdle()` (called every ~20ms)
2532. Don't repeatedly query values that haven't changed
2543. Use `device.setHasMeters()` only if peak meters are needed
255
256---
257
258## FAQ
259
260- **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 LEDs
263- **processMIDICC vs OnControlChange:** Use `On*` callbacks for modern code
264- **GUI access:** Limited through `ui` module; full UI automation not available
265- **Multiple devices:** Check `device.getName()` to identify, handle per-port
266
267---
268
269## Resources
270
271- **Official FL Studio API:** https://www.image-line.com/fl-studio/modules/python-scripting/
272- **PyFLP GitHub:** https://github.com/demberto/PyFLP
273- **API Functions:** 427+ across 14 modules | **Last Updated:** 2025