-
Notifications
You must be signed in to change notification settings - Fork 25
Using FFmpegKitNext on Linux
This page shows how to use FFmpegKitNext from a Linux C++ application after the Linux headers and shared libraries
have already been added to the application.
Use the headers for the features you need:
#include <FFmpegKit.h>
#include <FFmpegKitConfig.h>
#include <FFprobeKit.h>
using namespace ffmpegkit;Use execute for synchronous execution. It returns an FFmpegSession with the result, logs, statistics and failure
details.
auto session = FFmpegKit::execute("-y -i input.mp4 -c:v mpeg4 output.mp4");
auto returnCode = session->getReturnCode();
if (ReturnCode::isSuccess(returnCode)) {
std::cout << "FFmpeg completed successfully." << std::endl;
} else if (ReturnCode::isCancel(returnCode)) {
std::cout << "FFmpeg command was cancelled." << std::endl;
} else {
std::cout << "FFmpeg failed with state "
<< FFmpegKitConfig::sessionStateToString(session->getState())
<< " and rc " << returnCode << "."
<< session->getFailStackTrace() << std::endl;
}Use executeWithArguments when paths, filter expressions, or user-provided values may contain spaces or shell-sensitive
characters.
std::list<std::string> arguments = {
"-y",
"-i", "/tmp/input with spaces.mp4",
"-vf", "scale=1280:-2",
"-c:v", "mpeg4",
"/tmp/output.mp4"
};
auto session = FFmpegKit::executeWithArguments(arguments);executeAsync starts the command and returns immediately. Use the session callback for the final result, the log
callback for FFmpeg log lines and the statistics callback for progress information.
auto asyncSession = FFmpegKit::executeAsync(
"-y -i input.mp4 -c:v mpeg4 output.mp4",
[](const std::shared_ptr<FFmpegSession> session) {
auto returnCode = session->getReturnCode();
std::cout << "FFmpeg ended with state "
<< FFmpegKitConfig::sessionStateToString(session->getState())
<< " and rc " << returnCode << "." << std::endl;
},
[](const std::shared_ptr<Log> log) {
std::cout << log->getMessage();
},
[](const std::shared_ptr<Statistics> statistics) {
std::cout << "frame=" << statistics->getVideoFrameNumber()
<< " time=" << statistics->getTime()
<< " speed=" << statistics->getSpeed() << std::endl;
});Each execution creates a session. Use it to inspect the command, state, output, logs, statistics and timing.
auto session = FFmpegKit::execute("-y -i input.mp4 -f null -");
long sessionId = session->getSessionId();
std::string command = session->getCommand();
auto arguments = session->getArguments();
SessionState state = session->getState();
auto returnCode = session->getReturnCode();
auto startTime = session->getStartTime();
auto endTime = session->getEndTime();
long durationMs = session->getDuration();
std::string output = session->getOutput();
std::string failStackTrace = session->getFailStackTrace();
auto logs = session->getAllLogs();
auto statistics = session->getAllStatistics();
auto lastStatistics = session->getLastReceivedStatistics();For asynchronous sessions, getAllLogs() and getAllStatistics() wait for pending asynchronous messages. getLogs()
and getStatistics() return only the messages already delivered.
Session history is managed by FFmpegKitConfig.
FFmpegKitConfig::setSessionHistorySize(100);
auto sessions = FFmpegKitConfig::getSessions();
int index = 0;
for (const auto &session : *sessions) {
std::cout << "Session " << index++
<< " id=" << session->getSessionId()
<< " state=" << FFmpegKitConfig::sessionStateToString(session->getState())
<< " durationMs=" << session->getDuration()
<< " rc=" << session->getReturnCode()
<< std::endl;
}
auto runningSessions = FFmpegKitConfig::getSessionsByState(SessionStateRunning);
auto ffmpegSessions = FFmpegKitConfig::getFFmpegSessions();
auto ffprobeSessions = FFmpegKitConfig::getFFprobeSessions();
auto mediaInformationSessions = FFmpegKitConfig::getMediaInformationSessions();You can also retrieve FFmpegKitConfig::getLastSession(), FFmpegKitConfig::getLastCompletedSession(), or
FFmpegKitConfig::getSession(sessionId). Use deleteSession(sessionId) or clearSessions() only when you no longer
need the session history; callbacks cannot be triggered for deleted sessions.
Use FFprobeKit for direct ffprobe commands.
auto probeSession = FFprobeKit::execute(
"-v error -show_entries format=duration "
"-of default=noprint_wrappers=1:nokey=1 input.mp4");
if (!ReturnCode::isSuccess(probeSession->getReturnCode())) {
std::cout << "FFprobe failed. Output: "
<< probeSession->getAllLogsAsString() << std::endl;
}The same command can run asynchronously:
auto asyncProbeSession = FFprobeKit::executeAsync(
"-v error -show_streams -of json input.mp4",
[](const std::shared_ptr<FFprobeSession> session) {
std::cout << "FFprobe rc=" << session->getReturnCode() << std::endl;
});For parsed media metadata, use getMediaInformation.
auto mediaSession = FFprobeKit::getMediaInformation("input.mp4");
auto mediaInformation = mediaSession->getMediaInformation();
if (mediaInformation != nullptr) {
auto duration = mediaInformation->getDuration();
auto format = mediaInformation->getFormat();
auto streams = mediaInformation->getStreams();
if (duration != nullptr) {
std::cout << "duration=" << *duration << std::endl;
}
if (format != nullptr) {
std::cout << "format=" << *format << std::endl;
}
if (streams != nullptr) {
std::cout << "stream count=" << streams->size() << std::endl;
}
}Keep log redirection enabled when using getMediaInformation; disabling redirection prevents media information parsing
from receiving the JSON output it needs.
Cancellation returns immediately. Check the complete callback or session state later to observe the final result.
auto session = FFmpegKit::executeAsync(
"-i input.mp4 -c:v mpeg4 output.mp4",
[](const std::shared_ptr<FFmpegSession> completedSession) {
if (ReturnCode::isCancel(completedSession->getReturnCode())) {
std::cout << "Cancelled." << std::endl;
}
});
FFmpegKit::cancel(session->getSessionId());
// Or cancel every running FFmpeg session.
FFmpegKit::cancel();Redirection is enabled by default. With redirection enabled, sessions collect logs and statistics, global/session callbacks receive messages and media information parsing works.
FFmpegKitConfig::setLogLevel(LevelAVLogInfo);
FFmpegKitConfig::enableLogCallback(
[](const std::shared_ptr<Log> log) {
std::cout << FFmpegKitConfig::logLevelToString(log->getLevel())
<< ": " << log->getMessage();
});
FFmpegKitConfig::enableStatisticsCallback(
[](const std::shared_ptr<Statistics> statistics) {
std::cout << "session=" << statistics->getSessionId()
<< " frame=" << statistics->getVideoFrameNumber()
<< " bitrate=" << statistics->getBitrate()
<< std::endl;
});
FFmpegKitConfig::enableFFmpegSessionCompleteCallback(
[](const std::shared_ptr<FFmpegSession> session) {
std::cout << "FFmpeg session " << session->getSessionId()
<< " completed." << std::endl;
});
FFmpegKitConfig::enableFFprobeSessionCompleteCallback(
[](const std::shared_ptr<FFprobeSession> session) {
std::cout << "FFprobe session " << session->getSessionId()
<< " completed." << std::endl;
});
FFmpegKitConfig::enableMediaInformationSessionCompleteCallback(
[](const std::shared_ptr<MediaInformationSession> session) {
std::cout << "Media information session " << session->getSessionId()
<< " completed." << std::endl;
});Disable a previously registered global callback by passing nullptr.
FFmpegKitConfig::enableLogCallback(nullptr);
FFmpegKitConfig::enableStatisticsCallback(nullptr);
FFmpegKitConfig::enableFFmpegSessionCompleteCallback(nullptr);Use the log redirection strategy when you need to control whether logs are printed to stderr in addition to being
collected by the API.
FFmpegKitConfig::setLogRedirectionStrategy(
LogRedirectionStrategyPrintLogsWhenNoCallbacksDefined);Use FFmpegKitConfig::disableRedirection() only when you want FFmpeg and FFprobe output to go directly to stderr
and you do not need logs, statistics callbacks, or getMediaInformation.
The drawtext filter requires a Linux build that includes freetype and harfbuzz. Registering directories and using
font family names additionally requires fontconfig.
If the command can use a font file directly, pass fontfile:
auto session = FFmpegKit::execute(
"-y -i input.mp4 "
"-vf \"drawtext=fontfile=/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf:"
"text='Hello':x=20:y=20:fontsize=32:fontcolor=white\" "
"output.mp4");If fontconfig is enabled, register directories and optional friendly names:
FFmpegKitConfig::setFontDirectoryList(
std::list<std::string>{"/usr/share/fonts", "/usr/local/share/fonts"},
std::map<std::string, std::string>{{"MyFont", "My Font"}});
auto session = FFmpegKit::execute(
"-y -i input.mp4 "
"-vf \"drawtext=font='MyFont':text='Hello':x=20:y=20\" "
"output.mp4");If your application ships a custom fonts.conf, point fontconfig to that configuration directory:
int result = FFmpegKitConfig::setFontconfigConfigurationPath("/opt/myapp/fontconfig");FFmpegKitInputBuffer and FFmpegKitOutputBuffer expose finite, seekable in-memory resources through ffkitmem:
URLs. They are useful when you already have bytes in memory or want the encoded output as bytes without writing a
temporary file.
std::vector<uint8_t> inputBytes = loadInputBytes();
auto input = FFmpegKitInputBuffer::fromByteArray(inputBytes, "mp4");
auto output = FFmpegKitOutputBuffer::create("mp4");
std::list<std::string> arguments = {
"-y",
"-i", input->getUrl(),
"-c:v", "mpeg4",
"-f", "mp4",
output->getUrl()
};
auto session = FFmpegKit::executeWithArguments(arguments);
if (ReturnCode::isSuccess(session->getReturnCode())) {
auto outputBytes = output->toByteArray();
std::cout << "encoded bytes=" << outputBytes->size() << std::endl;
}
input->close();
output->close();fromBytes(data, size, extension) is available when your input is already in a raw byte pointer. create(extension, initialCapacity, maxCapacity) lets you control the output buffer capacity.
FFmpegKitStreamInput and FFmpegKitStreamOutput expose non-seekable memory-backed streams through ffkitstream:
URLs. Use them for producer/consumer flows. Use ffkitmem: instead when the format needs seeking.
auto streamInput = FFmpegKitStreamInput::create("raw");
auto streamOutput = FFmpegKitStreamOutput::create("wav");
std::list<std::string> arguments = {
"-f", "s16le",
"-ar", "48000",
"-ac", "2",
"-i", streamInput->getUrl(),
"-f", "wav",
streamOutput->getUrl()
};
auto session = FFmpegKit::executeWithArgumentsAsync(
arguments,
[](const std::shared_ptr<FFmpegSession> session) {
std::cout << "streaming session rc=" << session->getReturnCode() << std::endl;
});
std::vector<uint8_t> pcmChunk = readNextPcmChunk();
streamInput->write(pcmChunk, 1000);
streamInput->closeInput();
auto encodedChunk = streamOutput->read(4096, 1000);
if (encodedChunk != nullptr && !encodedChunk->empty()) {
consumeEncodedBytes(*encodedChunk);
}
streamInput->close();
streamOutput->close();A stream read(maxBytes, timeoutMs) returns nullptr on timeout and an empty vector at EOF. Read output while the
session runs if the produced data may exceed the stream capacity.
Use a named pipe when you need a filesystem path that another part of your application can write to while FFmpeg
reads from it.
auto pipePath = FFmpegKitConfig::registerNewFFmpegPipe();
if (pipePath != nullptr) {
std::list<std::string> arguments = {
"-y",
"-i", *pipePath,
"-c:v", "mpeg4",
"output.mp4"
};
auto session = FFmpegKit::executeWithArgumentsAsync(
arguments,
[](const std::shared_ptr<FFmpegSession> session) {
std::cout << "pipe session rc=" << session->getReturnCode() << std::endl;
});
std::ofstream writer(*pipePath, std::ios::binary);
std::vector<uint8_t> bytes = readBytesForPipe();
writer.write(reinterpret_cast<const char *>(bytes.data()), bytes.size());
writer.close();
FFmpegKitConfig::closeFFmpegPipe(*pipePath);
}Close every pipe created with registerNewFFmpegPipe() after the command and writer finish.
Use the configuration and package helpers to inspect the runtime your application loaded.
#include <ArchDetect.h>
#include <Packages.h>
std::cout << "FFmpegKit version: " << FFmpegKitConfig::getVersion() << std::endl;
std::cout << "FFmpeg version: " << FFmpegKitConfig::getFFmpegVersion() << std::endl;
std::cout << "Build date: " << FFmpegKitConfig::getBuildDate() << std::endl;
std::cout << "Package name: " << Packages::getPackageName() << std::endl;
std::cout << "Architecture: " << ArchDetect::getArch() << std::endl;
auto libraries = Packages::getExternalLibraries();
if (libraries->find("freetype") != libraries->end() &&
libraries->find("harfbuzz") != libraries->end()) {
std::cout << "drawtext dependencies are available." << std::endl;
}Packages::getExternalLibraries() returns enabled external library identifiers such as freetype, harfbuzz,
fontconfig, x264, x265, or gnutls.
Packages::getPackageName() returns the custom package name configured at build time.
Set process environment variables before running sessions when an FFmpeg library or protocol needs them:
int result = FFmpegKitConfig::setEnvironmentVariable("SSL_CERT_FILE", "/etc/ssl/certs/ca-certificates.crt");If your application owns signal handling, you can tell FFmpegKit to ignore specific signals:
FFmpegKitConfig::ignoreSignal(SignalPipe);
FFmpegKitConfig::ignoreSignal(SignalXcpu);For runnable Linux examples, see the test applications in the ffmpeg-kit-next-test project. It contains C++ examples for command execution, audio/video operations, subtitles, pipes, concurrent execution, HTTPS,
ffkitmem:/ffkitstream: protocols, media information parsing and other runtime API features.
Copyright (c) 2026 FFmpegKitNext
- Status
- Versions
- Changelog
- Project Layout
- Using
- Building
- External Libraries
- Patents
- License