Embed mpv as a playback backend in your application using the libmpv C API
libmpv provides a C API for embedding mpv’s playback engine into other applications. The API is licensed under ISC, while the mpv core itself is GPLv2+ by default (or LGPLv2.1+ when built with -Dgpl=false).
The API version is encoded as MPV_CLIENT_API_VERSION. The current version is MPV_MAKE_VERSION(2, 5). Changes to the C API are documented in DOCS/client-api-changes.rst.
Call mpv_create() to allocate a new mpv instance. The instance is in a pre-initialized state — no playback occurs yet.
mpv_handle *mpv = mpv_create();if (!mpv) { // out of memory, or LC_NUMERIC is not "C" exit(1);}
2
Set options
Use mpv_set_property() or mpv_set_property_string() to configure the instance before initialization. Some options (e.g. config, config-dir, input-conf, load-scripts, script, player-operation-mode) must be set before mpv_initialize().
// Create a new mpv instance (pre-initialized, not yet started)mpv_handle *mpv_create(void);// Initialize a created instance; must be called before most API useint mpv_initialize(mpv_handle *ctx);// Detach the handle; destroys the core if this was the last handlevoid mpv_destroy(mpv_handle *ctx);// Quit the player, wait for all handles to be destroyed, then returnvoid mpv_terminate_destroy(mpv_handle *ctx);// Create an additional client handle connected to the same corempv_handle *mpv_create_client(mpv_handle *ctx, const char *name);// Like mpv_create_client(), but the handle is a weak referencempv_handle *mpv_create_weak_client(mpv_handle *ctx, const char *name);// Return the name of this client handleconst char *mpv_client_name(mpv_handle *ctx);// Return the unique numeric ID of this client handleint64_t mpv_client_id(mpv_handle *ctx);// Return the compiled API versionunsigned long mpv_client_api_version(void);
// Send a command as a NULL-terminated string arrayint mpv_command(mpv_handle *ctx, const char **args);// Send a command using input.conf parsing (enables OSD and string expansion)int mpv_command_string(mpv_handle *ctx, const char *args);// Send a command as a structured mpv_nodeint mpv_command_node(mpv_handle *ctx, mpv_node *args, mpv_node *result);// Like mpv_command(), but also returns result dataint mpv_command_ret(mpv_handle *ctx, const char **args, mpv_node *result);// Send a command asynchronously; result is delivered as MPV_EVENT_COMMAND_REPLYint mpv_command_async(mpv_handle *ctx, uint64_t reply_userdata, const char **args);// Async version of mpv_command_node()int mpv_command_node_async(mpv_handle *ctx, uint64_t reply_userdata, mpv_node *args);// Signal async requests with the matching ID to abortvoid mpv_abort_async_command(mpv_handle *ctx, uint64_t reply_userdata);
Properties are runtime variables that control and report playback state. Writing to pause pauses playback; reading time-pos returns the current position.
// Set a property (supports all mpv_format types)int mpv_set_property(mpv_handle *ctx, const char *name, mpv_format format, void *data);// Set a property to a string valueint mpv_set_property_string(mpv_handle *ctx, const char *name, const char *data);// Delete a property (equivalent to "del [name]" command)int mpv_del_property(mpv_handle *ctx, const char *name);// Set a property asynchronously; result: MPV_EVENT_SET_PROPERTY_REPLYint mpv_set_property_async(mpv_handle *ctx, uint64_t reply_userdata, const char *name, mpv_format format, void *data);// Read a property valueint mpv_get_property(mpv_handle *ctx, const char *name, mpv_format format, void *data);// Read a property value as a string (caller must mpv_free() the result)char *mpv_get_property_string(mpv_handle *ctx, const char *name);// Read a property value formatted for OSD displaychar *mpv_get_property_osd_string(mpv_handle *ctx, const char *name);// Read a property asynchronously; result: MPV_EVENT_GET_PROPERTY_REPLYint mpv_get_property_async(mpv_handle *ctx, uint64_t reply_userdata, const char *name, mpv_format format);// Watch a property; changes are reported as MPV_EVENT_PROPERTY_CHANGEint mpv_observe_property(mpv_handle *mpv, uint64_t reply_userdata, const char *name, mpv_format format);// Stop watching a property registered with the given reply_userdataint mpv_unobserve_property(mpv_handle *mpv, uint64_t registered_reply_userdata);
// Load a config file (parses it as if mpv_set_option_string() was called)int mpv_load_config_file(mpv_handle *ctx, const char *filename);// Set an option before mpv_initialize() (semi-deprecated; prefer mpv_set_property())int mpv_set_option(mpv_handle *ctx, const char *name, mpv_format format, void *data);// Set an option to a string valueint mpv_set_option_string(mpv_handle *ctx, const char *name, const char *data);
// Block until an event is available, timeout expires, or mpv_wakeup() is called// Pass timeout=-1 to wait indefinitely; timeout=0 to poll without blockingmpv_event *mpv_wait_event(mpv_handle *ctx, double timeout);// Wake up a blocked mpv_wait_event() call from another threadvoid mpv_wakeup(mpv_handle *ctx);// Set a callback invoked when new events are available (do not call API from it)void mpv_set_wakeup_callback(mpv_handle *ctx, void (*cb)(void *d), void *d);// Block until all pending async requests have completedvoid mpv_wait_async_requests(mpv_handle *ctx);// Enable or disable a specific event typeint mpv_request_event(mpv_handle *ctx, mpv_event_id event, int enable);// Enable log message delivery at the specified minimum levelint mpv_request_log_messages(mpv_handle *ctx, const char *min_level);// Convert an mpv_event to an mpv_node map representationint mpv_event_to_node(mpv_node *dst, mpv_event *src);
Hooks are synchronous events that block the player until your code calls mpv_hook_continue().
// Register a hook handler (priority 0 is neutral; lower priority runs first)int mpv_hook_add(mpv_handle *ctx, uint64_t reply_userdata, const char *name, int priority);// Signal that hook handling is complete and the player may continueint mpv_hook_continue(mpv_handle *ctx, uint64_t id);
// Internal time in nanoseconds (not related to playback position)int64_t mpv_get_time_ns(mpv_handle *ctx);// Same, in microsecondsint64_t mpv_get_time_us(mpv_handle *ctx);// Free memory allocated by the API (e.g. strings from mpv_get_property_string)void mpv_free(void *data);// Free data referenced by an mpv_node (does not free the node itself)void mpv_free_node_contents(mpv_node *node);
// Create a render context (call before playback starts)int mpv_render_context_create(mpv_render_context **res, mpv_handle *mpv, mpv_render_param *params);// Set a callback invoked when a new frame is ready to rendervoid mpv_render_context_set_update_callback(mpv_render_context *ctx, mpv_render_update_fn callback, void *callback_ctx);// Query what should happen next (returns mpv_render_update_flag bitmask)uint64_t mpv_render_context_update(mpv_render_context *ctx);// Render the current video frame to the target surfaceint mpv_render_context_render(mpv_render_context *ctx, mpv_render_param *params);// Notify mpv that a frame was displayed (helps with A/V sync)void mpv_render_context_report_swap(mpv_render_context *ctx);// Destroy the render contextvoid mpv_render_context_free(mpv_render_context *ctx);
Include render_gl.h and use MPV_RENDER_API_TYPE_OPENGL. You must supply a get_proc_address callback so mpv can resolve GL function pointers without linking to a GL library directly.
Render on a dedicated thread. Calling normal libmpv API functions from the render thread can cause deadlocks. See the Threading section in render.h for the full list of safe functions.
The client API is fully thread-safe unless otherwise noted. However, only one thread may call mpv_wait_event() on a given handle at a time. Functions that are explicitly safe to call from the render thread are annotated with “Safe to be called from mpv render API threads” in client.h.