Common interface for all FFmpegKit
sessions.
+ */
+export class Session {
+
+ /**
+ * Returns the session specific execute callback function.
+ *
+ * @return session specific execute callback function
+ */
+ getExecuteCallback() {
+ }
+
+ /**
+ * Returns the session specific log callback function.
+ *
+ * @return session specific log callback function
+ */
+ getLogCallback() {
+ }
+
+ /**
+ * Returns the session identifier.
+ *
+ * @return session identifier
+ */
+ getSessionId() {
+ }
+
+ /**
+ * Returns session create time.
+ *
+ * @return session create time
+ */
+ getCreateTime() {
+ }
+
+ /**
+ * Returns session start time.
+ *
+ * @return session start time
+ */
+ getStartTime() {
+ }
+
+ /**
+ * Returns session end time.
+ *
+ * @return session end time
+ */
+ getEndTime() {
+ }
+
+ /**
+ * Returns the time taken to execute this session.
+ *
+ * @return time taken to execute this session in milliseconds or zero (0) if the session is
+ * not over yet
+ */
+ getDuration() {
+ }
+
+ /**
+ * Returns command arguments as an array.
+ *
+ * @return command arguments as an array
+ */
+ getArguments() {
+ }
+
+ /**
+ * Returns command arguments as a concatenated string.
+ *
+ * @return command arguments as a concatenated string
+ */
+ getCommand() {
+ }
+
+ /**
+ * Returns all log entries generated for this session. If there are asynchronous
+ * messages that are not delivered yet, this method waits for them until the given timeout.
+ *
+ * @param waitTimeout wait timeout for asynchronous messages in milliseconds
+ * @return list of log entries generated for this session
+ */
+ getAllLogs(waitTimeout) {
+ }
+
+ /**
+ * Returns all log entries delivered for this session. Note that if there are asynchronous log
+ * messages that are not delivered yet, this method will not wait for them and will return
+ * immediately.
+ *
+ * @return list of log entries received for this session
+ */
+ getLogs() {
+ }
+
+ /**
+ * Returns all log entries generated for this session as a concatenated string. If there are
+ * asynchronous messages that are not delivered yet, this method waits for them until
+ * the given timeout.
+ *
+ * @param waitTimeout wait timeout for asynchronous messages in milliseconds
+ * @return all log entries generated for this session as a concatenated string
+ */
+ getAllLogsAsString(waitTimeout) {
+ }
+
+ /**
+ * Returns all log entries delivered for this session as a concatenated string. Note that if
+ * there are asynchronous log messages that are not delivered yet, this method will not wait
+ * for them and will return immediately.
+ *
+ * @return list of log entries received for this session
+ */
+ getLogsAsString() {
+ }
+
+ /**
+ * Returns the log output generated while running the session.
+ *
+ * @return log output generated
+ */
+ getOutput() {
+ }
+
+ /**
+ * Returns the state of the session.
+ *
+ * @return state of the session
+ */
+ getState() {
+ }
+
+ /**
+ * Returns the return code for this session. Note that return code is only set for sessions
+ * that end with COMPLETED state. If a session is not started, still running or failed then
+ * this method returns undefined.
+ *
+ * @return the return code for this session if the session is COMPLETED, undefined if session is
+ * not started, still running or failed
+ */
+ getReturnCode() {
+ }
+
+ /**
+ * Returns the stack trace of the exception received while executing this session.
+ *
+ * The stack trace is only set for sessions that end with FAILED state. For sessions that has
+ * COMPLETED state this method returns undefined.
+ *
+ * @return stack trace of the exception received while executing this session, undefined if session
+ * is not started, still running or completed
+ */
+ getFailStackTrace() {
+ }
+
+ /**
+ * Returns session specific log redirection strategy.
+ *
+ * @return session specific log redirection strategy
+ */
+ getLogRedirectionStrategy() {
+ }
+
+ /**
+ * Returns whether there are still asynchronous messages being transmitted for this
+ * session or not.
+ *
+ * @return true if there are still asynchronous messages being transmitted, false
+ * otherwise
+ */
+ thereAreAsynchronousMessagesInTransmit() {
+ }
+
+ /**
+ * Returns whether it is an FFmpeg
session or not.
+ *
+ * @return true if it is an FFmpeg
session, false otherwise
+ */
+ isFFmpeg() {
+ }
+
+ /**
+ * Returns whether it is an FFprobe
session or not.
+ *
+ * @return true if it is an FFprobe
session, false otherwise
+ */
+ isFFprobe() {
+ }
+
+ /**
+ * Cancels running the session.
+ */
+ cancel() {
+ }
+
+}
+
+/**
+ * Abstract session implementation which includes common features shared by FFmpeg
+ * and FFprobe
sessions.
+ */
+export class AbstractSession extends Session {
+
+ /**
+ * Defines how long default "getAll" methods wait, in milliseconds.
+ */
+ static DEFAULT_TIMEOUT_FOR_ASYNCHRONOUS_MESSAGES_IN_TRANSMIT = 5000;
+
+ /**
+ * Session identifier.
+ */
+ #sessionId;
+
+ /**
+ * Date and time the session was created.
+ */
+ #createTime;
+
+ /**
+ * Date and time the session was started.
+ */
+ #startTime;
+
+ /**
+ * Command string.
+ */
+ #command;
+
+ /**
+ * Command arguments as an array.
+ */
+ #argumentsArray;
+
+ /**
+ * Session specific log redirection strategy.
+ */
+ #logRedirectionStrategy;
+
+ /**
+ * Creates a new abstract session.
+ */
+ constructor() {
+ super();
+ }
+
+ /**
+ * Creates a new FFmpeg session.
+ *
+ * @param argumentsArray FFmpeg command arguments
+ * @param logRedirectionStrategy defines how logs will be redirected
+ * @returns FFmpeg session created
+ */
+ static async createFFmpegSession(argumentsArray, logRedirectionStrategy) {
+ await FFmpegKitConfig.init();
+
+ if (logRedirectionStrategy === undefined) {
+ logRedirectionStrategy = FFmpegKitConfig.getLogRedirectionStrategy();
+ }
+
+ let nativeSession = await FFmpegKitReactNativeModule.ffmpegSession(argumentsArray);
+ let session = new FFmpegSession();
+
+ session.#sessionId = nativeSession.sessionId;
+ session.#createTime = FFmpegKitFactory.validDate(nativeSession.createTime);
+ session.#startTime = FFmpegKitFactory.validDate(nativeSession.startTime);
+ session.#command = nativeSession.command;
+ session.#argumentsArray = argumentsArray;
+ session.#logRedirectionStrategy = logRedirectionStrategy;
+
+ FFmpegKitFactory.setLogRedirectionStrategy(session.#sessionId, logRedirectionStrategy);
+
+ return session;
+ }
+
+ /**
+ * Creates a new FFmpeg session from the given map.
+ *
+ * @param sessionMap map that includes session fields as map keys
+ * @returns FFmpeg session created
+ */
+ static createFFmpegSessionFromMap(sessionMap) {
+ let session = new FFmpegSession();
+
+ session.#sessionId = sessionMap.sessionId;
+ session.#createTime = FFmpegKitFactory.validDate(sessionMap.createTime);
+ session.#startTime = FFmpegKitFactory.validDate(sessionMap.startTime);
+ session.#command = sessionMap.command;
+ session.#argumentsArray = FFmpegKitConfig.parseArguments(sessionMap.command);
+ session.#logRedirectionStrategy = FFmpegKitFactory.getLogRedirectionStrategy(session.#sessionId);
+
+ return session;
+ }
+
+ /**
+ * Creates a new FFprobe session.
+ *
+ * @param argumentsArray FFprobe command arguments
+ * @param logRedirectionStrategy defines how logs will be redirected
+ * @returns FFprobe session created
+ */
+ static async createFFprobeSession(argumentsArray, logRedirectionStrategy) {
+ await FFmpegKitConfig.init();
+
+ if (logRedirectionStrategy === undefined) {
+ logRedirectionStrategy = FFmpegKitConfig.getLogRedirectionStrategy();
+ }
+
+ let nativeSession = await FFmpegKitReactNativeModule.ffprobeSession(argumentsArray);
+ let session = new FFprobeSession();
+
+ session.#sessionId = nativeSession.sessionId;
+ session.#createTime = FFmpegKitFactory.validDate(nativeSession.createTime);
+ session.#startTime = FFmpegKitFactory.validDate(nativeSession.startTime);
+ session.#command = nativeSession.command;
+ session.#argumentsArray = argumentsArray;
+ session.#logRedirectionStrategy = logRedirectionStrategy;
+
+ FFmpegKitFactory.setLogRedirectionStrategy(session.#sessionId, logRedirectionStrategy);
+
+ return session;
+ }
+
+ /**
+ * Creates a new FFprobe session from the given map.
+ *
+ * @param sessionMap map that includes session fields as map keys
+ * @returns FFprobe session created
+ */
+ static createFFprobeSessionFromMap(sessionMap) {
+ let session = new FFprobeSession();
+
+ session.#sessionId = sessionMap.sessionId;
+ session.#createTime = FFmpegKitFactory.validDate(sessionMap.createTime);
+ session.#startTime = FFmpegKitFactory.validDate(sessionMap.startTime);
+ session.#command = sessionMap.command;
+ session.#argumentsArray = FFmpegKitConfig.parseArguments(sessionMap.command);
+ session.#logRedirectionStrategy = FFmpegKitFactory.getLogRedirectionStrategy(session.#sessionId);
+
+ return session;
+ }
+
+ /**
+ * Creates a new MediaInformationSession session.
+ *
+ * @param argumentsArray FFprobe command arguments
+ * @returns MediaInformationSession session created
+ */
+ static async createMediaInformationSession(argumentsArray) {
+ await FFmpegKitConfig.init();
+
+ let nativeSession = await FFmpegKitReactNativeModule.mediaInformationSession(argumentsArray);
+ let session = new MediaInformationSession();
+
+ session.#sessionId = nativeSession.sessionId;
+ session.#createTime = FFmpegKitFactory.validDate(nativeSession.createTime);
+ session.#startTime = FFmpegKitFactory.validDate(nativeSession.startTime);
+ session.#command = nativeSession.command;
+ session.#argumentsArray = argumentsArray;
+ session.#logRedirectionStrategy = LogRedirectionStrategy.NEVER_PRINT_LOGS;
+
+ FFmpegKitFactory.setLogRedirectionStrategy(session.#sessionId, LogRedirectionStrategy.NEVER_PRINT_LOGS);
+
+ return session;
+ }
+
+ /**
+ * Creates a new MediaInformationSession from the given map.
+ *
+ * @param sessionMap map that includes session fields as map keys
+ * @returns MediaInformationSession created
+ */
+ static createMediaInformationSessionFromMap(sessionMap) {
+ let session = new MediaInformationSession();
+
+ session.#sessionId = sessionMap.sessionId;
+ session.#createTime = FFmpegKitFactory.validDate(sessionMap.createTime);
+ session.#startTime = FFmpegKitFactory.validDate(sessionMap.startTime);
+ session.#command = sessionMap.command;
+ session.#argumentsArray = FFmpegKitConfig.parseArguments(sessionMap.command);
+ session.#logRedirectionStrategy = LogRedirectionStrategy.NEVER_PRINT_LOGS;
+
+ if (sessionMap.mediaInformation !== undefined && sessionMap.mediaInformation !== null) {
+ session.setMediaInformation(new MediaInformation(sessionMap.mediaInformation));
+ }
+
+ return session;
+ }
+
+ /**
+ * Returns the session specific execute callback function.
+ *
+ * @return session specific execute callback function
+ */
+ getExecuteCallback() {
+ return FFmpegKitFactory.getExecuteCallback(this.getSessionId())
+ }
+
+ /**
+ * Returns the session specific log callback function.
+ *
+ * @return session specific log callback function
+ */
+ getLogCallback() {
+ return FFmpegKitFactory.getLogCallback(this.getSessionId())
+ }
+
+ /**
+ * Returns the session identifier.
+ *
+ * @return session identifier
+ */
+ getSessionId() {
+ return this.#sessionId;
+ }
+
+ /**
+ * Returns session create time.
+ *
+ * @return session create time
+ */
+ getCreateTime() {
+ return this.#createTime;
+ }
+
+ /**
+ * Returns session start time.
+ *
+ * @return session start time
+ */
+ getStartTime() {
+ return this.#startTime;
+ }
+
+ /**
+ * Returns session end time.
+ *
+ * @return session end time
+ */
+ async getEndTime() {
+ const endTime = FFmpegKitReactNativeModule.abstractSessionGetEndTime(this.getSessionId());
+ return FFmpegKitFactory.validDate(endTime);
+ }
+
+ /**
+ * Returns the time taken to execute this session.
+ *
+ * @return time taken to execute this session in milliseconds or zero (0) if the session is
+ * not over yet
+ */
+ getDuration() {
+ return FFmpegKitReactNativeModule.abstractSessionGetDuration(this.getSessionId());
+ }
+
+ /**
+ * Returns command arguments as an array.
+ *
+ * @return command arguments as an array
+ */
+ getArguments() {
+ return this.#argumentsArray;
+ }
+
+ /**
+ * Returns command arguments as a concatenated string.
+ *
+ * @return command arguments as a concatenated string
+ */
+ getCommand() {
+ return this.#command;
+ }
+
+ /**
+ * Returns all log entries generated for this session. If there are asynchronous
+ * messages that are not delivered yet, this method waits for them until the given timeout.
+ *
+ * @param waitTimeout wait timeout for asynchronous messages in milliseconds
+ * @return list of log entries generated for this session
+ */
+ async getAllLogs(waitTimeout) {
+ const allLogs = await FFmpegKitReactNativeModule.abstractSessionGetAllLogs(this.getSessionId(), FFmpegKitFactory.optionalNumericParameter(waitTimeout));
+ return allLogs.map(FFmpegKitFactory.mapToLog);
+ }
+
+ /**
+ * Returns all log entries delivered for this session. Note that if there are asynchronous log
+ * messages that are not delivered yet, this method will not wait for them and will return
+ * immediately.
+ *
+ * @return list of log entries received for this session
+ */
+ async getLogs() {
+ const logs = await FFmpegKitReactNativeModule.abstractSessionGetLogs(this.getSessionId());
+ return logs.map(FFmpegKitFactory.mapToLog);
+ }
+
+ /**
+ * Returns all log entries generated for this session as a concatenated string. If there are
+ * asynchronous messages that are not delivered yet, this method waits for them until
+ * the given timeout.
+ *
+ * @param waitTimeout wait timeout for asynchronous messages in milliseconds
+ * @return all log entries generated for this session as a concatenated string
+ */
+ async getAllLogsAsString(waitTimeout) {
+ return FFmpegKitReactNativeModule.abstractSessionGetAllLogsAsString(this.getSessionId(), FFmpegKitFactory.optionalNumericParameter(waitTimeout));
+ }
+
+ /**
+ * Returns all log entries delivered for this session as a concatenated string. Note that if
+ * there are asynchronous log messages that are not delivered yet, this method will not wait
+ * for them and will return immediately.
+ *
+ * @return list of log entries received for this session
+ */
+ async getLogsAsString() {
+ let logs = await this.getLogs();
+
+ let concatenatedString = '';
+
+ logs.forEach(log => concatenatedString += log.getMessage());
+
+ return concatenatedString;
+ }
+
+ /**
+ * Returns the log output generated while running the session.
+ *
+ * @return log output generated
+ */
+ async getOutput() {
+ return this.getAllLogsAsString();
+ }
+
+ /**
+ * Returns the state of the session.
+ *
+ * @return state of the session
+ */
+ async getState() {
+ return FFmpegKitReactNativeModule.abstractSessionGetState(this.getSessionId());
+ }
+
+ /**
+ * Returns the return code for this session. Note that return code is only set for sessions
+ * that end with COMPLETED state. If a session is not started, still running or failed then
+ * this method returns undefined.
+ *
+ * @return the return code for this session if the session is COMPLETED, undefined if session is
+ * not started, still running or failed
+ */
+ async getReturnCode() {
+ const returnCodeValue = await FFmpegKitReactNativeModule.abstractSessionGetReturnCode(this.getSessionId());
+ if (returnCodeValue === undefined) {
+ return undefined;
+ } else {
+ return new ReturnCode(returnCodeValue);
+ }
+ }
+
+ /**
+ * Returns the stack trace of the exception received while executing this session.
+ *
+ * The stack trace is only set for sessions that end with FAILED state. For sessions that has
+ * COMPLETED state this method returns undefined.
+ *
+ * @return stack trace of the exception received while executing this session, undefined if session
+ * is not started, still running or completed
+ */
+ getFailStackTrace() {
+ return FFmpegKitReactNativeModule.abstractSessionGetFailStackTrace(this.getSessionId());
+ }
+
+ /**
+ * Returns session specific log redirection strategy.
+ *
+ * @return session specific log redirection strategy
+ */
+ getLogRedirectionStrategy() {
+ return this.#logRedirectionStrategy;
+ }
+
+ /**
+ * Returns whether there are still asynchronous messages being transmitted for this
+ * session or not.
+ *
+ * @return true if there are still asynchronous messages being transmitted, false
+ * otherwise
+ */
+ thereAreAsynchronousMessagesInTransmit() {
+ return FFmpegKitReactNativeModule.abstractSessionThereAreAsynchronousMessagesInTransmit(this.getSessionId());
+ }
+
+ /**
+ * Returns whether it is an FFmpeg
session or not.
+ *
+ * @return true if it is an FFmpeg
session, false otherwise
+ */
+ isFFmpeg() {
+ return false;
+ }
+
+ /**
+ * Returns whether it is an FFprobe
session or not.
+ *
+ * @return true if it is an FFprobe
session, false otherwise
+ */
+ isFFprobe() {
+ return false;
+ }
+
+ /**
+ * Cancels running the session.
+ */
+ cancel() {
+ if (sessionId === undefined) {
+ return FFmpegKitReactNativeModule.cancel();
+ } else {
+ return FFmpegKitReactNativeModule.cancelSession(sessionId);
+ }
+ }
+
+}
+
+/**
+ * Detects the running architecture.
+ */
+export class ArchDetect {
+
+ /**
+ * Returns architecture name loaded.
+ *
+ * @return architecture name loaded
+ */
+ static async getArch() {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.getArch();
+ }
+
+}
+
+/**
+ *
Main class to run FFmpeg
commands.
+ */
+export class FFmpegKit {
+
+ /**
+ *
Asynchronously executes FFmpeg with command provided. + * + * @param command FFmpeg command + * @param executeCallback callback that will be called when the execution is completed + * @param logCallback callback that will receive logs + * @param statisticsCallback callback that will receive statistics + * @return FFmpeg session created for this execution + */ + static async executeAsync(command, executeCallback, logCallback, statisticsCallback) { + return FFmpegKit.executeWithArgumentsAsync(FFmpegKitConfig.parseArguments(command), executeCallback, logCallback, statisticsCallback); + } + + /** + *
Asynchronously executes FFmpeg with arguments provided. + * + * @param commandArguments FFmpeg command options/arguments as string array + * @param executeCallback callback that will be called when the execution is completed + * @param logCallback callback that will receive logs + * @param statisticsCallback callback that will receive statistics + * @return FFmpeg session created for this execution + */ + static async executeWithArgumentsAsync(commandArguments, executeCallback, logCallback, statisticsCallback) { + let session = await FFmpegSession.create(commandArguments, executeCallback, logCallback, statisticsCallback); + + await FFmpegKitConfig.asyncFFmpegExecute(session); + + return session; + } + + /** + *
Cancels the session specified with sessionId
.
+ *
+ *
This function does not wait for termination to complete and returns immediately. + * + * @param sessionId id of the session that will be cancelled + */ + static async cancel(sessionId) { + await FFmpegKitConfig.init(); + + if (sessionId === undefined) { + return FFmpegKitReactNativeModule.cancel(); + } else { + return FFmpegKitReactNativeModule.cancelSession(sessionId); + } + } + + /** + *
Lists all FFmpeg sessions in the session history. + * + * @return all FFmpeg sessions in the session history + */ + static async listSessions() { + await FFmpegKitConfig.init(); + + const sessionArray = await FFmpegKitReactNativeModule.getFFmpegSessions(); + return sessionArray.map(FFmpegKitFactory.mapToSession); + } + +} + +/** + *
Configuration class of FFmpegKit
library.
+ */
+export class FFmpegKitConfig {
+
+ static #globalLogRedirectionStrategy = LogRedirectionStrategy.PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED;
+
+ /**
+ * Initializes the library asynchronously.
+ */
+ static async init() {
+ await FFmpegKitInitializer.initialize();
+ }
+
+ /**
+ *
Enables log and statistics redirection. + * + *
When redirection is enabled FFmpeg/FFprobe logs are redirected to console and sessions + * collect log and statistics entries for the executions. It is possible to define global or + * session specific log/statistics callbacks as well. + * + *
Note that redirection is enabled by default. If you do not want to use its functionality + * please use {@link #disableRedirection()} to disable it. + */ + static async enableRedirection() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.enableRedirection(); + } + + /** + *
Disables log and statistics redirection. + * + *
When redirection is disabled logs are printed to stderr, all logs and statistics
+ * callbacks are disabled and FFprobe
's getMediaInformation
methods
+ * do not work.
+ */
+ static async disableRedirection() {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.disableRedirection();
+ }
+
+ /**
+ *
Sets and overrides fontconfig
configuration directory.
+ *
+ * @param path directory that contains fontconfig configuration (fonts.conf)
+ * @return zero on success, non-zero on error
+ */
+ static async setFontconfigConfigurationPath(path) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.setFontconfigConfigurationPath(path);
+ }
+
+ /**
+ *
Registers the fonts inside the given path, so they become available to use in FFmpeg + * filters. + * + *
Note that you need to use a package with fontconfig
inside to be
+ * able to use fonts in FFmpeg
.
+ *
+ * @param fontDirectoryPath directory that contains fonts (.ttf and .otf files)
+ * @param fontNameMapping custom font name mappings, useful to access your fonts with more
+ * friendly names
+ */
+ static async setFontDirectory(fontDirectoryPath, fontNameMapping) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.setFontDirectory(fontDirectoryPath, fontNameMapping);
+ }
+
+ /**
+ *
Registers the fonts inside the given list of font directories, so they become available + * to use in FFmpeg filters. + * + *
Note that you need to use a package with fontconfig
inside to be
+ * able to use fonts in FFmpeg
.
+ *
+ * @param fontDirectoryList list of directories that contain fonts (.ttf and .otf files)
+ * @param fontNameMapping custom font name mappings, useful to access your fonts with more
+ * friendly names
+ */
+ static async setFontDirectoryList(fontDirectoryList, fontNameMapping) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.setFontDirectoryList(fontDirectoryList, fontNameMapping);
+ }
+
+ /**
+ *
Creates a new named pipe to use in FFmpeg
operations.
+ *
+ *
Please note that creator is responsible of closing created pipes. + * + * @return the full path of the named pipe + */ + static async registerNewFFmpegPipe() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.registerNewFFmpegPipe(); + } + + /** + *
Closes a previously created FFmpeg
pipe.
+ *
+ * @param ffmpegPipePath full path of the FFmpeg pipe
+ */
+ static async closeFFmpegPipe(ffmpegPipePath) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.closeFFmpegPipe(ffmpegPipePath);
+ }
+
+ /**
+ *
Returns the version of FFmpeg bundled within FFmpegKit
library.
+ *
+ * @return the version of FFmpeg
+ */
+ static async getFFmpegVersion() {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.getFFmpegVersion();
+ }
+
+ /**
+ *
Returns FFmpegKit ReactNative library version. + * + * @return FFmpegKit version + */ + static async getVersion() { + return new Promise((resolve) => resolve(FFmpegKitFactory.getVersion())); + } + + /** + *
Returns whether FFmpegKit release is a Long Term Release or not. + * + * @return true/yes or false/no + */ + static async isLTSBuild() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.isLTSBuild(); + } + + /** + *
Returns FFmpegKit native library build date. + * + * @return FFmpegKit native library build date + */ + static async getBuildDate() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.getBuildDate(); + } + + /** + *
Sets an environment variable. + * + * @param variableName environment variable name + * @param variableValue environment variable value + * @return zero on success, non-zero on error + */ + static async setEnvironmentVariable(variableName, variableValue) { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.setEnvironmentVariable(variableName, variableValue); + } + + /** + *
Registers a new ignored signal. Ignored signals are not handled by FFmpegKit
+ * library.
+ *
+ * @param signal signal to be ignored
+ */
+ static async ignoreSignal(signal) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.ignoreSignal(signal);
+ }
+
+ /**
+ *
Asynchronously executes the FFmpeg session provided. + * + * @param ffmpegSession FFmpeg session which includes command options/arguments + */ + static async asyncFFmpegExecute(ffmpegSession) { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.asyncFFmpegSessionExecute(ffmpegSession.getSessionId()); + } + + /** + *
Asynchronously executes the FFprobe session provided. + * + * @param ffprobeSession FFprobe session which includes command options/arguments + */ + static async asyncFFprobeExecute(ffprobeSession) { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.asyncFFprobeSessionExecute(ffprobeSession.getSessionId()); + } + + /** + *
Asynchronously executes the media information session provided. + * + * @param mediaInformationSession media information session which includes command options/arguments + * @param waitTimeout max time to wait until media information is transmitted + */ + static async asyncGetMediaInformationExecute(mediaInformationSession, waitTimeout) { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.asyncMediaInformationSessionExecute(mediaInformationSession.getSessionId(), FFmpegKitFactory.optionalNumericParameter(waitTimeout)); + } + + /** + *
Sets a global callback function to redirect FFmpeg/FFprobe logs. + * + * @param logCallback log callback function or undefined to disable a previously defined + * callback + */ + static enableLogCallback(logCallback) { + FFmpegKitFactory.setGlobalLogCallback(logCallback); + } + + /** + *
Sets a global callback function to redirect FFmpeg statistics. + * + * @param statisticsCallback statistics callback function or undefined to disable a previously + * defined callback + */ + static enableStatisticsCallback(statisticsCallback) { + FFmpegKitFactory.setGlobalStatisticsCallback(statisticsCallback); + } + + /** + *
Sets a global callback function to receive execution results.
+ *
+ * @param executeCallback execute callback function or undefined to disable a previously
+ * defined callback
+ */
+ static enableExecuteCallback(executeCallback) {
+ FFmpegKitFactory.setGlobalExecuteCallback(executeCallback);
+ }
+
+ /**
+ * Returns the current log level.
+ *
+ * @return current log level
+ */
+ static getLogLevel() {
+ return FFmpegKitFactory.getLogLevel();
+ }
+
+ /**
+ * Sets the log level.
+ *
+ * @param level new log level
+ */
+ static async setLogLevel(level) {
+ await FFmpegKitConfig.init();
+
+ FFmpegKitFactory.setLogLevel(level);
+ return FFmpegKitReactNativeModule.setLogLevel(level);
+ }
+
+ /**
+ * Returns the session history size.
+ *
+ * @return session history size
+ */
+ static async getSessionHistorySize() {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.getSessionHistorySize();
+ }
+
+ /**
+ * Sets the session history size.
+ *
+ * @param sessionHistorySize session history size, should be smaller than 1000
+ */
+ static async setSessionHistorySize(sessionHistorySize) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.setSessionHistorySize(sessionHistorySize);
+ }
+
+ /**
+ * Returns the session specified with sessionId
from the session history.
+ *
+ * @param sessionId session identifier
+ * @return session specified with sessionId or undefined if it is not found in the history
+ */
+ static async getSession(sessionId) {
+ await FFmpegKitConfig.init();
+
+ if (sessionId === undefined) {
+ return undefined;
+ } else {
+ const sessionMap = await FFmpegKitReactNativeModule.getSession(sessionId);
+ return FFmpegKitFactory.mapToSession(sessionMap);
+ }
+ }
+
+ /**
+ * Returns the last session created from the session history.
+ *
+ * @return the last session created or undefined if session history is empty
+ */
+ static async getLastSession() {
+ await FFmpegKitConfig.init();
+
+ const sessionMap = await FFmpegKitReactNativeModule.getLastSession();
+ return FFmpegKitFactory.mapToSession(sessionMap);
+ }
+
+ /**
+ * Returns the last session completed from the session history.
+ *
+ * @return the last session completed. If there are no completed sessions in the history this
+ * method will return undefined
+ */
+ static async getLastCompletedSession() {
+ await FFmpegKitConfig.init();
+
+ const sessionMap = await FFmpegKitReactNativeModule.getLastCompletedSession();
+ return FFmpegKitFactory.mapToSession(sessionMap);
+ }
+
+ /**
+ *
Returns all sessions in the session history. + * + * @return all sessions in the session history + */ + static async getSessions() { + await FFmpegKitConfig.init(); + + const sessionArray = await FFmpegKitReactNativeModule.getSessions(); + return sessionArray.map(FFmpegKitFactory.mapToSession); + } + + /** + *
Clears all, including ongoing, sessions in the session history. + *
Note that callbacks cannot be triggered for deleted sessions. + */ + static async clearSessions() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.clearSessions(); + } + + /** + *
Returns sessions that have the given state. + * + * @param state session state + * @return sessions that have the given state from the session history + */ + static async getSessionsByState(state) { + await FFmpegKitConfig.init(); + + const sessionArray = await FFmpegKitReactNativeModule.getSessionsByState(state); + return sessionArray.map(FFmpegKitFactory.mapToSession); + } + + /** + * Returns the active log redirection strategy. + * + * @return log redirection strategy + */ + static getLogRedirectionStrategy() { + return this.#globalLogRedirectionStrategy; + } + + /** + *
Sets the log redirection strategy. + * + * @param logRedirectionStrategy log redirection strategy + */ + static setLogRedirectionStrategy(logRedirectionStrategy) { + this.#globalLogRedirectionStrategy = logRedirectionStrategy; + } + + /** + *
Returns the number of messages that are not transmitted to the ReactNative callbacks yet for + * this session. + * + * @param sessionId id of the session + * @return number of messages that are not transmitted to the ReactNative callbacks yet for + * this session + */ + static async messagesInTransmit(sessionId) { + await FFmpegKitConfig.init(); + + const sessionMap = await FFmpegKitReactNativeModule.messagesInTransmit(sessionId); + return FFmpegKitFactory.mapToSession(sessionMap); + } + + /** + * Returns the string representation of the SessionState provided. + * + * @param state session state instance + * @returns string representation of the SessionState provided + */ + static sessionStateToString(state) { + switch (state) { + case SessionState.CREATED: + return "CREATED"; + case SessionState.RUNNING: + return "RUNNING"; + case SessionState.FAILED: + return "FAILED"; + case SessionState.COMPLETED: + return "COMPLETED"; + default: + return ""; + } + } + + /** + *
Parses the given command into arguments. Uses space character to split the arguments. + * Supports single and double quote characters. + * + * @param command string command + * @return array of arguments + */ + static parseArguments(command) { + let argumentList = []; + let currentArgument = ""; + + let singleQuoteStarted = 0; + let doubleQuoteStarted = 0; + + for (let i = 0; i < command.length; i++) { + let previousChar; + if (i > 0) { + previousChar = command.charAt(i - 1); + } else { + previousChar = null; + } + let currentChar = command.charAt(i); + + if (currentChar === ' ') { + if (singleQuoteStarted === 1 || doubleQuoteStarted === 1) { + currentArgument += currentChar; + } else if (currentArgument.length > 0) { + argumentList.push(currentArgument); + currentArgument = ""; + } + } else if (currentChar === '\'' && (previousChar == null || previousChar !== '\\')) { + if (singleQuoteStarted === 1) { + singleQuoteStarted = 0; + } else if (doubleQuoteStarted === 1) { + currentArgument += currentChar; + } else { + singleQuoteStarted = 1; + } + } else if (currentChar === '\"' && (previousChar == null || previousChar !== '\\')) { + if (doubleQuoteStarted === 1) { + doubleQuoteStarted = 0; + } else if (singleQuoteStarted === 1) { + currentArgument += currentChar; + } else { + doubleQuoteStarted = 1; + } + } else { + currentArgument += currentChar; + } + } + + if (currentArgument.length > 0) { + argumentList.push(currentArgument); + } + + return argumentList; + } + + /** + *
Concatenates arguments into a string adding a space character between two arguments. + * + * @param commandArguments arguments + * @return concatenated string containing all arguments + */ + static argumentsToString(commandArguments) { + if (commandArguments === undefined) { + return 'undefined'; + } + + let command = ''; + + function appendArgument(value, index) { + if (index > 0) { + command += ' '; + } + command += value; + } + + commandArguments.forEach(appendArgument); + return command; + } + + // THE FOLLOWING TWO METHODS ARE REACT-NATIVE SPECIFIC + + /** + * Enables logs. + */ + static async enableLogs() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.enableLogs(); + } + + /** + * Disable logs. + */ + static async disableLogs() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.disableLogs(); + } + + /** + * Enables statistics. + */ + static async enableStatistics() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.enableStatistics(); + } + + /** + * Disables statistics. + */ + static async disableStatistics() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.disableStatistics(); + } + + /** + * Returns the platform name the library is loaded on. + */ + static async getPlatform() { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.getPlatform(); + } + + /** + * Writes the given file to a pipe. + * + * @param inputPath input file path + * @param pipePath pipe path + * @returns zero on success, non-zero on error + */ + static async writeToPipe(inputPath, pipePath) { + await FFmpegKitConfig.init(); + + return FFmpegKitReactNativeModule.writeToPipe(inputPath, pipePath); + } + + /** + *
Displays the native file dialog to select a file in read mode. If a file is selected then this + * method returns the Structured Access Framework Uri for that file. + * + *
Note that this method is Android only. It will fail if called on other platforms.
+ *
+ * @param type specifies a mime type for the file dialog
+ * @param extraTypes additional mime types
+ * @returns Structured Access Framework Uri ("content:…"
) of the file selected or undefined
+ * if no files are selected
+ */
+ static async selectDocumentForRead(type, extraTypes) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.selectDocument(false, undefined, type, extraTypes);
+ }
+
+ /**
+ *
Displays the native file dialog to select a file in write mode. If a file is selected then this + * method returns the Structured Access Framework Uri for that file. + * + *
Note that this method is Android only. It will fail if called on other platforms.
+ *
+ * @param title file name
+ * @param type specifies a mime type for the file dialog
+ * @param extraTypes additional mime types
+ * @returns Structured Access Framework Uri ("content:…"
) of the file selected or undefined
+ * if no files are selected
+ */
+ static async selectDocumentForWrite(title, type, extraTypes) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.selectDocument(true, title, type, extraTypes);
+ }
+
+ /**
+ *
Converts the given Structured Access Framework Uri into an input url that can be used in FFmpeg + * and FFprobe commands. + * + *
Note that this method is Android only. It will fail if called on other platforms. It also requires
+ * API Level ≥ 19. On older API levels it returns an empty url.
+ *
+ * @param uriString SAF uri ("content:…"
)
+ * @return input url that can be passed to FFmpegKit or FFprobeKit
+ */
+ static async getSafParameterForRead(uriString) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.getSafParameter(false, uriString);
+ }
+
+ /**
+ *
Converts the given Structured Access Framework Uri into an output url that can be used in FFmpeg + * and FFprobe commands. + * + *
Note that this method is Android only. It will fail if called on other platforms. It also requires
+ * API Level ≥ 19. On older API levels it returns an empty url.
+ *
+ * @param uriString SAF uri ("content:…"
)
+ * @return output url that can be passed to FFmpegKit or FFprobeKit
+ */
+ static async getSafParameterForWrite(uriString) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.getSafParameter(true, uriString);
+ }
+
+}
+
+class FFmpegKitFactory {
+
+ static #logCallback = undefined;
+ static #statisticsCallback = undefined;
+ static #executeCallback = undefined;
+ static #activeLogLevel = undefined;
+
+ static mapToStatistics(statisticsMap) {
+ if (statisticsMap !== undefined) {
+ return new Statistics(
+ statisticsMap.sessionId,
+ statisticsMap.videoFrameNumber,
+ statisticsMap.videoFps,
+ statisticsMap.videoQuality,
+ statisticsMap.size,
+ statisticsMap.time,
+ statisticsMap.bitrate,
+ statisticsMap.speed
+ );
+ } else {
+ return undefined;
+ }
+ }
+
+ static mapToLog(logMap) {
+ if (logMap !== undefined) {
+ return new Log(logMap.sessionId, logMap.level, logMap.message)
+ } else {
+ return undefined;
+ }
+ }
+
+ static mapToSession(sessionMap) {
+ if (sessionMap !== undefined) {
+ switch (sessionMap.type) {
+ case 2:
+ return FFprobeSession.fromMap(sessionMap);
+ case 3:
+ return MediaInformationSession.fromMap(sessionMap);
+ case 1:
+ default:
+ return FFmpegSession.fromMap(sessionMap);
+ }
+ } else {
+ return undefined;
+ }
+ }
+
+ static getVersion() {
+ return "4.5";
+ }
+
+ static getLogRedirectionStrategy(sessionId) {
+ return logRedirectionStrategyMap.get(sessionId);
+ }
+
+ static setLogRedirectionStrategy(sessionId, logRedirectionStrategy) {
+ logRedirectionStrategyMap.set(sessionId, logRedirectionStrategy);
+ }
+
+ static getLogCallback(sessionId) {
+ return logCallbackMap.get(sessionId);
+ }
+
+ static setLogCallback(sessionId, logCallback) {
+ if (logCallback !== undefined) {
+ logCallbackMap.set(sessionId, logCallback);
+ }
+ }
+
+ static getGlobalLogCallback() {
+ return this.#logCallback;
+ }
+
+ static setGlobalLogCallback(logCallback) {
+ this.#logCallback = logCallback;
+ }
+
+ static getStatisticsCallback(sessionId) {
+ return statisticsCallbackMap.get(sessionId);
+ }
+
+ static setStatisticsCallback(sessionId, statisticsCallback) {
+ if (statisticsCallback !== undefined) {
+ statisticsCallbackMap.set(sessionId, statisticsCallback);
+ }
+ }
+
+ static getGlobalStatisticsCallback() {
+ return this.#statisticsCallback;
+ }
+
+ static setGlobalStatisticsCallback(statisticsCallback) {
+ this.#statisticsCallback = statisticsCallback;
+ }
+
+ static getExecuteCallback(sessionId) {
+ return executeCallbackMap.get(sessionId);
+ }
+
+ static setExecuteCallback(sessionId, executeCallback) {
+ if (executeCallback !== undefined) {
+ executeCallbackMap.set(sessionId, executeCallback);
+ }
+ }
+
+ static getGlobalExecuteCallback() {
+ return this.#executeCallback;
+ }
+
+ static setGlobalExecuteCallback(executeCallback) {
+ this.#executeCallback = executeCallback;
+ }
+
+ static setLogLevel(logLevel) {
+ this.#activeLogLevel = logLevel;
+ }
+
+ static getLogLevel() {
+ return this.#activeLogLevel;
+ }
+
+ static optionalNumericParameter(value) {
+ return value ?? -1;
+ }
+
+ static validDate(time) {
+ if (time === undefined || time === null || time <= 0) {
+ return undefined;
+ } else {
+ return new Date(time);
+ }
+ }
+
+}
+
+class FFmpegKitInitializer {
+ static #initialized = false;
+ static #eventEmitter = new FFmpegKitReactNativeEventEmitter();
+
+ static processLogCallbackEvent(event) {
+ const log = FFmpegKitFactory.mapToLog(event)
+ const sessionId = event.sessionId;
+ const level = event.level;
+ const text = event.message;
+ const activeLogLevel = FFmpegKitConfig.getLogLevel();
+ let globalCallbackDefined = false;
+ let sessionCallbackDefined = false;
+ let activeLogRedirectionStrategy = FFmpegKitConfig.getLogRedirectionStrategy();
+
+ // AV_LOG_STDERR logs are always redirected
+ if ((activeLogLevel === Level.AV_LOG_QUIET && level !== Level.AV_LOG_STDERR) || level > activeLogLevel) {
+ // LOG NEITHER PRINTED NOR FORWARDED
+ return;
+ }
+
+ FFmpegKitConfig.getSession(sessionId).then(session => {
+ activeLogRedirectionStrategy = session.getLogRedirectionStrategy();
+
+ if (session.getLogCallback() !== undefined) {
+ sessionCallbackDefined = true;
+
+ try {
+ // NOTIFY SESSION CALLBACK DEFINED
+ session.getLogCallback()(log);
+ } catch (err) {
+ console.log("Exception thrown inside session LogCallback block.", err.stack);
+ }
+ }
+
+ let globalLogCallbackFunction = FFmpegKitFactory.getGlobalLogCallback();
+ if (globalLogCallbackFunction !== undefined) {
+ globalCallbackDefined = true;
+
+ try {
+ // NOTIFY GLOBAL CALLBACK DEFINED
+ globalLogCallbackFunction(log);
+ } catch (err) {
+ console.log("Exception thrown inside global LogCallback block.", err.stack);
+ }
+ }
+
+ // EXECUTE THE LOG STRATEGY
+ switch (activeLogRedirectionStrategy) {
+ case LogRedirectionStrategy.NEVER_PRINT_LOGS: {
+ return;
+ }
+ case LogRedirectionStrategy.PRINT_LOGS_WHEN_GLOBAL_CALLBACK_NOT_DEFINED: {
+ if (globalCallbackDefined) {
+ return;
+ }
+ }
+ break;
+ case LogRedirectionStrategy.PRINT_LOGS_WHEN_SESSION_CALLBACK_NOT_DEFINED: {
+ if (sessionCallbackDefined) {
+ return;
+ }
+ }
+ break;
+ case LogRedirectionStrategy.PRINT_LOGS_WHEN_NO_CALLBACKS_DEFINED: {
+ if (globalCallbackDefined || sessionCallbackDefined) {
+ return;
+ }
+ }
+ break;
+ case LogRedirectionStrategy.ALWAYS_PRINT_LOGS: {
+ }
+ break;
+ }
+
+ // PRINT LOGS
+ switch (level) {
+ case Level.AV_LOG_QUIET: {
+ // PRINT NO OUTPUT
+ }
+ break;
+ default: {
+ console.log(text);
+ }
+ }
+ });
+ }
+
+ static processStatisticsCallbackEvent(event) {
+ let statistics = FFmpegKitFactory.mapToStatistics(event);
+ let sessionId = event.sessionId;
+
+ FFmpegKitConfig.getSession(sessionId).then(session => {
+ if (session.isFFmpeg()) {
+ if (session.getStatisticsCallback() !== undefined) {
+ try {
+ // NOTIFY SESSION CALLBACK DEFINED
+ session.getStatisticsCallback()(statistics);
+ } catch (err) {
+ console.log("Exception thrown inside session StatisticsCallback block.", err.stack);
+ }
+ }
+ }
+
+ let globalStatisticsCallbackFunction = FFmpegKitFactory.getGlobalStatisticsCallback();
+ if (globalStatisticsCallbackFunction !== undefined) {
+ try {
+ // NOTIFY GLOBAL CALLBACK DEFINED
+ globalStatisticsCallbackFunction(statistics);
+ } catch (err) {
+ console.log("Exception thrown inside global StatisticsCallback block.", err.stack);
+ }
+ }
+ });
+ }
+
+ static processExecuteCallbackEvent(event) {
+ let sessionId = event.sessionId;
+
+ FFmpegKitConfig.getSession(sessionId).then(session => {
+ if (session.getExecuteCallback() !== undefined) {
+ try {
+ // NOTIFY SESSION CALLBACK DEFINED
+ session.getExecuteCallback()(session);
+ } catch (err) {
+ console.log("Exception thrown inside session ExecuteCallback block.", err.stack);
+ }
+ }
+
+ let globalExecuteCallbackFunction = FFmpegKitFactory.getGlobalExecuteCallback();
+ if (globalExecuteCallbackFunction !== undefined) {
+ try {
+ // NOTIFY GLOBAL CALLBACK DEFINED
+ globalExecuteCallbackFunction(session);
+ } catch (err) {
+ console.log("Exception thrown inside global ExecuteCallback block.", err.stack);
+ }
+ }
+ });
+ }
+
+ static async initialize() {
+ if (this.#initialized) {
+ return;
+ } else {
+ this.#initialized = true;
+ }
+
+ console.log("Loading ffmpeg-kit-react-native.");
+
+ this.#eventEmitter.addListener(eventLogCallbackEvent, FFmpegKitInitializer.processLogCallbackEvent);
+ this.#eventEmitter.addListener(eventStatisticsCallbackEvent, FFmpegKitInitializer.processStatisticsCallbackEvent);
+ this.#eventEmitter.addListener(eventExecuteCallbackEvent, FFmpegKitInitializer.processExecuteCallbackEvent);
+
+ FFmpegKitFactory.setLogLevel(await FFmpegKitReactNativeModule.getLogLevel());
+ const version = FFmpegKitFactory.getVersion();
+ const platform = await FFmpegKitConfig.getPlatform();
+ const arch = await ArchDetect.getArch();
+ const packageName = await Packages.getPackageName();
+ await FFmpegKitConfig.enableRedirection();
+
+ console.log(`Loaded ffmpeg-kit-react-native-${platform}-${packageName}-${arch}-${version}.`);
+ }
+
+}
+
+/**
+ *
An FFmpeg session. + */ +export class FFmpegSession extends AbstractSession { + + /** + * Creates an empty FFmpeg session. + */ + constructor() { + super(); + } + + /** + * Creates a new FFmpeg session. + * + * @param argumentsArray FFmpeg command arguments + * @param executeCallback callback that will be called when the execution is completed + * @param logCallback callback that will receive logs + * @param statisticsCallback callback that will receive statistics + * @param logRedirectionStrategy defines how logs will be redirected + * @returns FFmpeg session created + */ + static async create(argumentsArray, executeCallback, logCallback, statisticsCallback, logRedirectionStrategy) { + const session = await AbstractSession.createFFmpegSession(argumentsArray, logRedirectionStrategy); + const sessionId = session.getSessionId(); + + FFmpegKitFactory.setExecuteCallback(sessionId, executeCallback); + FFmpegKitFactory.setLogCallback(sessionId, logCallback); + FFmpegKitFactory.setStatisticsCallback(sessionId, statisticsCallback); + + return session; + } + + /** + * Creates a new FFmpeg session from the given map. + * + * @param sessionMap map that includes session fields as map keys + * @returns FFmpeg session created + */ + static fromMap(sessionMap) { + return AbstractSession.createFFmpegSessionFromMap(sessionMap); + } + + /** + * Returns the session specific statistics callback function. + * + * @return session specific statistics callback function + */ + getStatisticsCallback() { + return FFmpegKitFactory.getStatisticsCallback(this.getSessionId()); + } + + /** + * Returns all statistics entries generated for this session. If there are asynchronous + * messages that are not delivered yet, this method waits for them until the given timeout. + * + * @param waitTimeout wait timeout for asynchronous messages in milliseconds + * @return list of statistics entries generated for this session + */ + async getAllStatistics(waitTimeout) { + await FFmpegKitConfig.init(); + + const allStatistics = await FFmpegKitReactNativeModule.ffmpegSessionGetAllStatistics(this.getSessionId(), FFmpegKitFactory.optionalNumericParameter(waitTimeout)); + return allStatistics.map(FFmpegKitFactory.mapToStatistics); + } + + /** + * Returns all statistics entries delivered for this session. Note that if there are + * asynchronous messages that are not delivered yet, this method will not wait for + * them and will return immediately. + * + * @return list of statistics entries received for this session + */ + async getStatistics() { + await FFmpegKitConfig.init(); + + const statistics = await FFmpegKitReactNativeModule.ffmpegSessionGetStatistics(this.getSessionId()); + return statistics.map(FFmpegKitFactory.mapToStatistics); + } + + /** + * Returns the last received statistics entry. + * + * @return the last received statistics entry or undefined if there are not any statistics entries + * received + */ + async getLastReceivedStatistics() { + let statistics = await this.getStatistics(); + + if (statistics.length > 0) { + return statistics[0]; + } else { + return undefined; + } + } + + isFFmpeg() { + return true; + } + + isFFprobe() { + return false; + } + +} + +/** + *
Main class to run FFprobe
commands.
+ */
+export class FFprobeKit {
+
+ /**
+ *
Asynchronously executes FFprobe with arguments provided. + * + * @param command FFprobe command + * @param executeCallback callback that will be called when the execution is completed + * @param logCallback callback that will receive logs + * @return FFprobe session created for this execution + */ + static async executeAsync(command, executeCallback, logCallback) { + return FFprobeKit.executeWithArgumentsAsync(FFmpegKitConfig.parseArguments(command), executeCallback, logCallback); + } + + /** + *
Asynchronously executes FFprobe with arguments provided. + * + * @param commandArguments FFprobe command options/arguments as string array + * @param executeCallback callback that will be called when the execution is completed + * @param logCallback callback that will receive logs + * @return FFprobe session created for this execution + */ + static async executeWithArgumentsAsync(commandArguments, executeCallback, logCallback) { + let session = await FFprobeSession.create(commandArguments, executeCallback, logCallback); + + await FFmpegKitConfig.asyncFFprobeExecute(session); + + return session; + } + + /** + *
Extracts the media information for the specified file asynchronously. + * + * @param path path or uri of a media file + * @param executeCallback callback that will be notified when execution is completed + * @param logCallback callback that will receive logs + * @param waitTimeout max time to wait until media information is transmitted + * @return media information session created for this execution + */ + static async getMediaInformationAsync(path, executeCallback, logCallback, waitTimeout) { + const commandArguments = ["-v", "error", "-hide_banner", "-print_format", "json", "-show_format", "-show_streams", "-i", path]; + return FFprobeKit.getMediaInformationFromCommandArgumentsAsync(commandArguments, executeCallback, logCallback, waitTimeout); + } + + /** + *
Extracts media information using the command provided asynchronously. + * + * @param command FFprobe command that prints media information for a file in JSON format + * @param executeCallback callback that will be notified when execution is completed + * @param logCallback callback that will receive logs + * @param waitTimeout max time to wait until media information is transmitted + * @return media information session created for this execution + */ + static async getMediaInformationFromCommandAsync(command, executeCallback, logCallback, waitTimeout) { + return FFprobeKit.getMediaInformationFromCommandArgumentsAsync(FFmpegKitConfig.parseArguments(command), executeCallback, logCallback, waitTimeout); + } + + /** + *
Extracts media information using the command arguments provided asynchronously. + * + * @param commandArguments FFprobe command arguments that prints media information for a file in JSON format + * @param executeCallback callback that will be notified when execution is completed + * @param logCallback callback that will receive logs + * @param waitTimeout max time to wait until media information is transmitted + * @return media information session created for this execution + */ + static async getMediaInformationFromCommandArgumentsAsync(commandArguments, executeCallback, logCallback, waitTimeout) { + let session = await MediaInformationSession.create(commandArguments, executeCallback, logCallback); + + await FFmpegKitConfig.asyncGetMediaInformationExecute(session, waitTimeout); + + return session; + } + + /** + *
Lists all FFprobe sessions in the session history. + * + * @return all FFprobe sessions in the session history + */ + static async listSessions() { + await FFmpegKitConfig.init(); + + const sessionArray = await FFmpegKitReactNativeModule.getFFprobeSessions(); + return sessionArray.map(FFmpegKitFactory.mapToSession); + } + +} + +/** + *
An FFprobe session. + */ +export class FFprobeSession extends AbstractSession { + + /** + * Creates an empty FFprobe session. + */ + constructor() { + super(); + } + + /** + * Creates a new FFprobe session. + * + * @param argumentsArray FFprobe command arguments + * @param executeCallback callback that will be called when the execution is completed + * @param logCallback callback that will receive logs + * @param logRedirectionStrategy defines how logs will be redirected + * @returns FFprobe session created + */ + static async create(argumentsArray, executeCallback, logCallback, logRedirectionStrategy) { + const session = await AbstractSession.createFFprobeSession(argumentsArray, logRedirectionStrategy); + const sessionId = session.getSessionId(); + + FFmpegKitFactory.setExecuteCallback(sessionId, executeCallback); + FFmpegKitFactory.setLogCallback(sessionId, logCallback); + + return session; + } + + /** + * Creates a new FFprobe session from the given map. + * + * @param sessionMap map that includes session fields as map keys + * @returns FFprobe session created + */ + static fromMap(sessionMap) { + return AbstractSession.createFFprobeSessionFromMap(sessionMap); + } + + isFFmpeg() { + return false; + } + + isFFprobe() { + return true; + } + +} + +/** + *
Defines log levels. + */ +export class Level { + + /** + * This log level is used to specify logs printed to stderr by ffmpeg. + * Logs that has this level are not filtered and always redirected. + */ + static AV_LOG_STDERR = -16; + + /** + * Print no output. + */ + static AV_LOG_QUIET = -8; + + /** + * Something went really wrong and we will crash now. + */ + static AV_LOG_PANIC = 0; + + /** + * Something went wrong and recovery is not possible. + * For example, no header was found for a format which depends + * on headers or an illegal combination of parameters is used. + */ + static AV_LOG_FATAL = 8; + + /** + * Something went wrong and cannot losslessly be recovered. + * However, not all future data is affected. + */ + static AV_LOG_ERROR = 16; + + /** + * Something somehow does not look correct. This may or may not + * lead to problems. An example would be the use of '-vstrict -2'. + */ + static AV_LOG_WARNING = 24; + + /** + * Standard information. + */ + static AV_LOG_INFO = 32; + + /** + * Detailed information. + */ + static AV_LOG_VERBOSE = 40; + + /** + * Stuff which is only useful for libav* developers. + */ + static AV_LOG_DEBUG = 48; + + /** + * Extremely verbose debugging, useful for libav* development. + */ + static AV_LOG_TRACE = 56; + + /** + * Returns log level string. + * + * @param level log level integer + * @returns log level string + */ + static levelToString(level) { + switch (level) { + case Level.AV_LOG_TRACE: + return "TRACE"; + case Level.AV_LOG_DEBUG: + return "DEBUG"; + case Level.AV_LOG_VERBOSE: + return "VERBOSE"; + case Level.AV_LOG_INFO: + return "INFO"; + case Level.AV_LOG_WARNING: + return "WARNING"; + case Level.AV_LOG_ERROR: + return "ERROR"; + case Level.AV_LOG_FATAL: + return "FATAL"; + case Level.AV_LOG_PANIC: + return "PANIC"; + case Level.AV_LOG_STDERR: + return "STDERR"; + case Level.AV_LOG_QUIET: + default: + return ""; + } + } + +} + +/** + *
Log entry for an FFmpegKit
session.
+ */
+export class Log {
+ #sessionId;
+ #level;
+ #message;
+
+ constructor(sessionId, level, message) {
+ this.#sessionId = sessionId;
+ this.#level = level;
+ this.#message = message;
+ }
+
+ getSessionId() {
+ return this.#sessionId;
+ }
+
+ getLevel() {
+ return this.#level;
+ }
+
+ getMessage() {
+ return this.#message;
+ }
+
+}
+
+/**
+ * Media information class.
+ */
+export class MediaInformation {
+
+ static KEY_MEDIA_PROPERTIES = "format";
+ static KEY_FILENAME = "filename";
+ static KEY_FORMAT = "format_name";
+ static KEY_FORMAT_LONG = "format_long_name";
+ static KEY_START_TIME = "start_time";
+ static KEY_DURATION = "duration";
+ static KEY_SIZE = "size";
+ static KEY_BIT_RATE = "bit_rate";
+ static KEY_TAGS = "tags";
+
+ #allProperties;
+
+ constructor(properties) {
+ this.#allProperties = properties;
+ }
+
+ /**
+ * Returns file name.
+ *
+ * @return media file name
+ */
+ getFilename() {
+ return this.getStringProperty(MediaInformation.KEY_FILENAME);
+ }
+
+ /**
+ * Returns format.
+ *
+ * @return media format
+ */
+ getFormat() {
+ return this.getStringProperty(MediaInformation.KEY_FORMAT);
+ }
+
+ /**
+ * Returns long format.
+ *
+ * @return media long format
+ */
+ getLongFormat() {
+ return this.getStringProperty(MediaInformation.KEY_FORMAT_LONG);
+ }
+
+ /**
+ * Returns duration.
+ *
+ * @return media duration in milliseconds
+ */
+ getDuration() {
+ return this.getStringProperty(MediaInformation.KEY_DURATION);
+ }
+
+ /**
+ * Returns start time.
+ *
+ * @return media start time in milliseconds
+ */
+ getStartTime() {
+ return this.getStringProperty(MediaInformation.KEY_START_TIME);
+ }
+
+ /**
+ * Returns size.
+ *
+ * @return media size in bytes
+ */
+ getSize() {
+ return this.getStringProperty(MediaInformation.KEY_SIZE);
+ }
+
+ /**
+ * Returns bitrate.
+ *
+ * @return media bitrate in kb/s
+ */
+ getBitrate() {
+ return this.getStringProperty(MediaInformation.KEY_BIT_RATE);
+ }
+
+ /**
+ * Returns all tags.
+ *
+ * @return tags dictionary
+ */
+ getTags() {
+ return this.getProperties(MediaInformation.KEY_TAGS);
+ }
+
+ /**
+ * Returns the streams found as array.
+ *
+ * @returns StreamInformation array
+ */
+ getStreams() {
+ let list = [];
+ let streamList;
+
+ if (this.#allProperties !== undefined) {
+ streamList = this.#allProperties.streams;
+ }
+
+ if (streamList !== undefined) {
+ streamList.forEach((stream) => {
+ list.push(new StreamInformation(stream));
+ });
+ }
+
+ return list;
+ }
+
+ /**
+ * Returns the media property associated with the key.
+ *
+ * @param key property key
+ * @return media property as string or undefined if the key is not found
+ */
+ getStringProperty(key) {
+ let mediaProperties = this.getMediaProperties();
+ if (mediaProperties !== undefined) {
+ return mediaProperties[key];
+ } else {
+ return undefined;
+ }
+ }
+
+ /**
+ * Returns the media property associated with the key.
+ *
+ * @param key property key
+ * @return media property as number or undefined if the key is not found
+ */
+ getNumberProperty(key) {
+ let mediaProperties = this.getMediaProperties();
+ if (mediaProperties !== undefined) {
+ return mediaProperties[key];
+ } else {
+ return undefined;
+ }
+ }
+
+ /**
+ * Returns the media properties associated with the key.
+ *
+ * @param key properties key
+ * @return media properties as an object or undefined if the key is not found
+ */
+ getProperties(key) {
+ let mediaProperties = this.getMediaProperties();
+ if (mediaProperties !== undefined) {
+ return mediaProperties[key];
+ } else {
+ return undefined;
+ }
+ }
+
+ /**
+ * Returns all media properties.
+ *
+ * @returns an object where media properties can be accessed by property names
+ */
+ getMediaProperties() {
+ if (this.#allProperties !== undefined) {
+ return this.#allProperties.format;
+ } else {
+ return undefined;
+ }
+ }
+
+ /**
+ * Returns all properties found, including stream properties.
+ *
+ * @returns an object in which properties can be accessed by property names
+ */
+ getAllProperties() {
+ return this.#allProperties;
+ }
+}
+
+/**
+ * A parser that constructs {@link MediaInformation} from FFprobe's json output.
+ */
+export class MediaInformationJsonParser {
+
+ /**
+ * Extracts MediaInformation
from the given FFprobe json output. Note that this
+ * method does not fail as {@link #fromWithError(String)} does and returns undefined on error.
+ *
+ * @param ffprobeJsonOutput FFprobe json output
+ * @return created {@link MediaInformation} instance of undefined if a parsing error occurs
+ */
+ static async from(ffprobeJsonOutput) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.mediaInformationJsonParserFrom(ffprobeJsonOutput).map(properties => new MediaInformation(properties));
+ }
+
+ /**
+ * Extracts MediaInformation from the given FFprobe json output.
+ *
+ * @param ffprobeJsonOutput ffprobe json output
+ * @return created {@link MediaInformation} instance
+ */
+ static async fromWithError(ffprobeJsonOutput) {
+ await FFmpegKitConfig.init();
+
+ return FFmpegKitReactNativeModule.mediaInformationJsonParserFrom(ffprobeJsonOutput).map(properties => new MediaInformation(properties));
+ }
+
+}
+
+/**
+ *
A custom FFprobe session, which produces a MediaInformation
object using the
+ * FFprobe output.
+ */
+export class MediaInformationSession extends FFprobeSession {
+ #mediaInformation;
+
+ /**
+ * Creates an empty MediaInformationSession.
+ */
+ constructor() {
+ super();
+ }
+
+ /**
+ * Creates a new MediaInformationSession session.
+ *
+ * @param argumentsArray FFprobe command arguments
+ * @param executeCallback callback that will be called when the execution is completed
+ * @param logCallback callback that will receive logs
+ * @returns MediaInformationSession session created
+ */
+ static async create(argumentsArray, executeCallback, logCallback) {
+ const session = await AbstractSession.createMediaInformationSession(argumentsArray);
+ const sessionId = session.getSessionId();
+
+ FFmpegKitFactory.setExecuteCallback(sessionId, executeCallback);
+ FFmpegKitFactory.setLogCallback(sessionId, logCallback);
+
+ return session;
+ }
+
+ /**
+ * Creates a new MediaInformationSession from the given map.
+ *
+ * @param sessionMap map that includes session fields as map keys
+ * @returns MediaInformationSession created
+ */
+ static fromMap(sessionMap) {
+ return AbstractSession.createMediaInformationSessionFromMap(sessionMap);
+ }
+
+ /**
+ * Returns the media information extracted in this session.
+ *
+ * @return media information extracted or undefined if the command failed or the output can not be
+ * parsed
+ */
+ getMediaInformation() {
+ return this.#mediaInformation;
+ }
+
+ /**
+ * Sets the media information extracted in this session.
+ *
+ * @param mediaInformation media information extracted
+ */
+ setMediaInformation(mediaInformation) {
+ this.#mediaInformation = mediaInformation;
+ }
+
+}
+
+/**
+ *
Helper class to extract binary package information. + */ +export class Packages { + + /** + * Returns the FFmpegKit ReactNative binary package name. + * + * @return predicted FFmpegKit ReactNative binary package name + */ + static getPackageName() { + return FFmpegKitReactNativeModule.getPackageName(); + } + + /** + * Returns enabled external libraries by FFmpeg. + * + * @return enabled external libraries + */ + static getExternalLibraries() { + return FFmpegKitReactNativeModule.getExternalLibraries(); + } + +} + +export class ReturnCode { + + static SUCCESS = 0; + + static CANCEL = 255; + + #value; + + constructor(value) { + this.#value = value; + } + + static isSuccess(returnCode) { + return (returnCode !== undefined && returnCode.getValue() === ReturnCode.SUCCESS); + } + + static isCancel(returnCode) { + return (returnCode !== undefined && returnCode.getValue() === ReturnCode.CANCEL); + } + + getValue() { + return this.#value; + } + + isValueSuccess() { + return (this.#value === ReturnCode.SUCCESS); + } + + isValueError() { + return ((this.#value !== ReturnCode.SUCCESS) && (this.#value !== ReturnCode.CANCEL)); + } + + isValueCancel() { + return (this.#value === ReturnCode.CANCEL); + } + + toString() { + return this.#value; + } + +} + +/** + *
Statistics entry for an FFmpeg execute session. + */ +export class Statistics { + #sessionId; + #videoFrameNumber; + #videoFps; + #videoQuality; + #size; + #time; + #bitrate; + #speed; + + constructor(sessionId, videoFrameNumber, videoFps, videoQuality, size, time, bitrate, speed) { + this.#sessionId = sessionId; + this.#videoFrameNumber = videoFrameNumber; + this.#videoFps = videoFps; + this.#videoQuality = videoQuality; + this.#size = size; + this.#time = time; + this.#bitrate = bitrate; + this.#speed = speed; + } + + getSessionId() { + return this.#sessionId; + } + + setSessionId(sessionId) { + this.#sessionId = sessionId; + } + + getVideoFrameNumber() { + return this.#videoFrameNumber; + } + + setVideoFrameNumber(videoFrameNumber) { + this.#videoFrameNumber = videoFrameNumber; + } + + getVideoFps() { + return this.#videoFps; + } + + setVideoFps(videoFps) { + this.#videoFps = videoFps; + } + + getVideoQuality() { + return this.#videoQuality; + } + + setVideoQuality(videoQuality) { + this.#videoQuality = videoQuality; + } + + getSize() { + return this.#size; + } + + setSize(size) { + this.#size = size; + } + + getTime() { + return this.#time; + } + + setTime(time) { + this.#time = time; + } + + getBitrate() { + return this.#bitrate; + } + + setBitrate(bitrate) { + this.#bitrate = bitrate; + } + + getSpeed() { + return this.#speed; + } + + setSpeed(speed) { + this.#speed = speed; + } + +} + +/** + * Stream information class. + */ +export class StreamInformation { + + static KEY_INDEX = "index"; + static KEY_TYPE = "codec_type"; + static KEY_CODEC = "codec_name"; + static KEY_CODEC_LONG = "codec_long_name"; + static KEY_FORMAT = "pix_fmt"; + static KEY_WIDTH = "width"; + static KEY_HEIGHT = "height"; + static KEY_BIT_RATE = "bit_rate"; + static KEY_SAMPLE_RATE = "sample_rate"; + static KEY_SAMPLE_FORMAT = "sample_fmt"; + static KEY_CHANNEL_LAYOUT = "channel_layout"; + static KEY_SAMPLE_ASPECT_RATIO = "sample_aspect_ratio"; + static KEY_DISPLAY_ASPECT_RATIO = "display_aspect_ratio"; + static KEY_AVERAGE_FRAME_RATE = "avg_frame_rate"; + static KEY_REAL_FRAME_RATE = "r_frame_rate"; + static KEY_TIME_BASE = "time_base"; + static KEY_CODEC_TIME_BASE = "codec_time_base"; + static KEY_TAGS = "tags"; + + #allProperties; + + constructor(properties) { + this.#allProperties = properties; + } + + /** + * Returns stream index. + * + * @return stream index, starting from zero + */ + getIndex() { + return this.getNumberProperty(StreamInformation.KEY_INDEX); + } + + /** + * Returns stream type. + * + * @return stream type; audio or video + */ + getType() { + return this.getStringProperty(StreamInformation.KEY_TYPE); + } + + /** + * Returns stream codec. + * + * @return stream codec + */ + getCodec() { + return this.getStringProperty(StreamInformation.KEY_CODEC); + } + + /** + * Returns stream codec in long format. + * + * @return stream codec with additional profile and mode information + */ + getCodecLong() { + return this.getStringProperty(StreamInformation.KEY_CODEC_LONG); + } + + /** + * Returns stream format. + * + * @return stream format + */ + getFormat() { + return this.getStringProperty(StreamInformation.KEY_FORMAT); + } + + /** + * Returns width. + * + * @return width in pixels + */ + getWidth() { + return this.getNumberProperty(StreamInformation.KEY_WIDTH); + } + + /** + * Returns height. + * + * @return height in pixels + */ + getHeight() { + return this.getNumberProperty(StreamInformation.KEY_HEIGHT); + } + + /** + * Returns bitrate. + * + * @return bitrate in kb/s + */ + getBitrate() { + return this.getStringProperty(StreamInformation.KEY_BIT_RATE); + } + + /** + * Returns sample rate. + * + * @return sample rate in hz + */ + getSampleRate() { + return this.getStringProperty(StreamInformation.KEY_SAMPLE_RATE); + } + + /** + * Returns sample format. + * + * @return sample format + */ + getSampleFormat() { + return this.getStringProperty(StreamInformation.KEY_SAMPLE_FORMAT); + } + + /** + * Returns channel layout. + * + * @return channel layout + */ + getChannelLayout() { + return this.getStringProperty(StreamInformation.KEY_CHANNEL_LAYOUT); + } + + /** + * Returns sample aspect ratio. + * + * @return sample aspect ratio + */ + getSampleAspectRatio() { + return this.getStringProperty(StreamInformation.KEY_SAMPLE_ASPECT_RATIO); + } + + /** + * Returns display aspect ratio. + * + * @return display aspect ratio + */ + getDisplayAspectRatio() { + return this.getStringProperty(StreamInformation.KEY_DISPLAY_ASPECT_RATIO); + } + + /** + * Returns display aspect ratio. + * + * @return average frame rate in fps + */ + getAverageFrameRate() { + return this.getStringProperty(StreamInformation.KEY_AVERAGE_FRAME_RATE); + } + + /** + * Returns real frame rate. + * + * @return real frame rate in tbr + */ + getRealFrameRate() { + return this.getStringProperty(StreamInformation.KEY_REAL_FRAME_RATE); + } + + /** + * Returns time base. + * + * @return time base in tbn + */ + getTimeBase() { + return this.getStringProperty(StreamInformation.KEY_TIME_BASE); + } + + /** + * Returns codec time base. + * + * @return codec time base in tbc + */ + getCodecTimeBase() { + return this.getStringProperty(StreamInformation.KEY_CODEC_TIME_BASE); + } + + /** + * Returns all tags. + * + * @return tags object + */ + getTags() { + return this.getProperties(StreamInformation.KEY_TAGS); + } + + /** + * Returns the stream property associated with the key. + * + * @param key property key + * @return stream property as string or undefined if the key is not found + */ + getStringProperty(key) { + if (this.#allProperties !== undefined) { + return this.#allProperties[key]; + } else { + return undefined; + } + } + + /** + * Returns the stream property associated with the key. + * + * @param key property key + * @return stream property as number or undefined if the key is not found + */ + getNumberProperty(key) { + if (this.#allProperties !== undefined) { + return this.#allProperties[key]; + } else { + return undefined; + } + } + + /** + * Returns the stream properties associated with the key. + * + * @param key properties key + * @return stream properties as an object or undefined if the key is not found + */ + getProperties(key) { + if (this.#allProperties !== undefined) { + return this.#allProperties[key]; + } else { + return undefined; + } + } + + /** + * Returns all properties found. + * + * @returns an object in which properties can be accessed by property names + */ + getAllProperties() { + return this.#allProperties; + } +}