Package {tidymedia}


Title: Media File Preprocessing and Metadata for the 'tidyverse'
Version: 0.2.1
Description: Batch preprocessing and metadata extraction for audio, video and image files, built on the command-line programs 'FFmpeg' (https://ffmpeg.org/) and 'MediaInfo' (https://mediaarea.net/en/MediaInfo). Trim, crop, scale, convert and standardize files one at a time or across a whole directory, and read container and stream metadata back as tibbles for use with the 'tidyverse'.
License: GPL-3
URL: https://github.com/jmgirard/tidymedia, https://jmgirard.github.io/tidymedia/
BugReports: https://github.com/jmgirard/tidymedia/issues
Depends: R (≥ 4.1.0)
Imports: archive (≥ 1.1.1), cli (≥ 3.4.0), digest (≥ 0.6.37), dplyr (≥ 1.1.0), glue (≥ 1.6.2), purrr (≥ 1.0.0), rappdirs (≥ 0.3.3), rlang (≥ 1.2.0), tibble (≥ 3.1.4), tools, utils, withr (≥ 2.5.0)
Suggests: furrr (≥ 0.3.0), future (≥ 1.30.0), knitr (≥ 1.40), rmarkdown (≥ 2.16), roxygen2 (≥ 7.2.0), spelling (≥ 2.2), testthat (≥ 3.0.0)
SystemRequirements: FFmpeg (https://ffmpeg.org/), MediaInfo (https://mediaarea.net/en/MediaInfo)
VignetteBuilder: knitr
Encoding: UTF-8
Language: en-US
Config/testthat/edition: 3
Config/roxygen2/version: 8.1.0
Config/Needs/website: pkgdown
NeedsCompilation: no
Packaged: 2026-09-29 16:06:56 UTC; jmgirard
Author: Jeffrey Girard ORCID iD [aut, cre]
Maintainer: Jeffrey Girard <me@jmgirard.com>
Repository: CRAN
Date/Publication: 2026-10-10 10:30:02 UTC

tidymedia: Media File Preprocessing and Metadata for the 'tidyverse'

Description

tidymedia prepares audio and video files for research. It trims, crops, converts and standardizes files, and reads file details back as tibbles. It runs the programs FFmpeg and MediaInfo. Start with vignette("tidymedia").

Details

Task functions, such as extract_audio(), do one common job in one call. Pipeline functions, such as ffm_files(), build an FFmpeg command one step at a time. Direct commands, ffmpeg(), ffprobe() and mediainfo(), pass your own arguments to the programs. probe_all() and get_duration() read file details.

See vignette("tidymedia") for the guided tour and a glossary of media terms. The other vignettes are "batch", "metadata", "verification" and "workflow".

Session options

A new option value takes effect at the next call. The workers of a parallel = TRUE run use your session's values.

Errors when FFmpeg fails

Author(s)

Maintainer: Jeffrey Girard me@jmgirard.com (ORCID)

Authors:

See Also

Useful links:


Cover fixed regions of a video with opaque boxes

Description

Anonymize a video by covering one or more fixed rectangular regions with opaque filled boxes. For example, you can redact a face, a name badge, or a screen that stays in one place for the whole clip. The regions are fixed (there is no face or object tracking), so this suits footage where the areas to cover do not move. The glossary in vignette("tidymedia") explains media terms such as codec, pixel format and stream copy.

Usage

anonymize_video(
  infile,
  outfile,
  regions,
  color = "black",
  video_codec = "libx264",
  audio_codec = "copy",
  pixel_format = "yuv420p",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a video file.

outfile

A string containing the path of the video file to write.

regions

A data frame with one row per box and columns x, y, width, height (and optionally color); see Details.

color

A string naming the default fill color in FFmpeg color syntax, used for any row without its own color (default "black").

video_codec

A string naming the output video codec (default "libx264"). NULL emits no -codec:v and lets the output container's default encoder decide. NULL is how you opt out of the H.264 default for a container that does not hold it. For a .webm output, pass video_codec = NULL and audio_codec = NULL, because the default audio_codec = "copy" would otherwise carry a codec WebM cannot hold.

audio_codec

A string naming the output audio codec. The default "copy" stream-copies the source audio unchanged. Name a real encoder, such as "aac", when the source audio codec cannot be copied into the output container. NULL emits no -codec:a and lets the container's default encoder decide.

pixel_format

A string naming the output pixel format (default "yuv420p").

hardware

The encoder backend. "none" (default) uses the software video_codec. "nvenc" uses NVIDIA GPU encoding (H.264, HEVC and AV1), and "videotoolbox" uses Apple GPU encoding (H.264 and HEVC). A backend uses its own encoder for the family of video_codec. For example, "libx264" becomes "h264_nvenc" or "h264_videotoolbox". See has_hardware_encoder for availability and its caveats. This applies to video only. audio_codec is never hardware-accelerated. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE re-encodes with the software video_codec and a message. FALSE (default) aborts instead. This keeps output reproducible by never changing the codec silently. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default) to leave the encoder's own default in place. It is the encoder's own rate-control value, passed through unchanged. libx264 and libx265 read it as -crf (0 to 51). The nvenc encoders read it as -cq (0 to 51), and the videotoolbox encoders as -q:v (1 to 100). Each scale is its own: the same number means something different on each encoder. A value outside the encoder's range is refused. An encoder outside those seven, such as libvpx-vp9, is refused with quality set. So is a video_codec of "copy", or of NULL under hardware = "none". When fallback = TRUE falls back to software, the value is dropped and the message says so, because it belonged to the hardware encoder's scale.

audio_stream

The audio track to carry into the output, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. The every-track family reads NULL this way: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Details

regions is a data frame with one row per box and the columns x, y, width, and height. Each value is a pixel number or an FFmpeg expression such as "in_w/2". x and y give the top-left corner, and width and height give the size. An optional color column overrides the color argument for that row. Every box is a solid fill (FFmpeg's drawbox with t=fill). The function intentionally does not offer hollow outlines.

Because the function applies a filter, it re-encodes the video. The video_codec and pixel_format arguments set the encoding, and default to H.264 and yuv420p. The function floors odd source dimensions to even, so the output always encodes. yuv420p and libx264 require even dimensions, and the step changes nothing for input that is already even. The function stream-copies the audio unchanged (-c:a copy) unless audio_codec names an encoder. The same input and regions therefore always compile to a byte-identical command.

Value

The compiled FFmpeg command (invisibly when run = TRUE).

References

https://ffmpeg.org/ffmpeg-filters.html#drawbox

See Also

ffm_drawbox(), the pipeline function it wraps; has_hardware_encoder() for the hardware argument; anonymize_video_batch() for the many-file (batch) form.

Other task functions: anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Cover two fixed regions with black boxes
regions <- data.frame(
  x = c(10, 200), y = c(10, 150),
  width = c(120, 80), height = c(90, 60)
)
anonymize_video(video, "anon.mp4", regions, run = FALSE)
# Carry only the second audio track instead of all of them
anonymize_video(video, "anon.mp4", regions, audio_stream = 1, run = FALSE)

Anonymize Many Videos From a Jobs Table

Description

Cover fixed rectangular regions of many input videos with opaque filled boxes from a single jobs tibble. This is the batch (table-driven) form of anonymize_video(), for when you have more than one video to redact. Each row is one input with its own regions. The required columns name the source (input) and the boxes to cover (regions). This is a thin wrapper over ffm_batch. It compiles one reproducible command per input. It shares the same box-fill pipeline (and per-region validation) as anonymize_video(). The glossary in vignette("tidymedia") explains media terms such as codec, pixel format and stream copy.

Usage

anonymize_video_batch(
  jobs,
  color = "black",
  video_codec = "libx264",
  audio_codec = "copy",
  pixel_format = "yuv420p",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input and (at least) an input column (source path) and a regions list-column. Each regions cell is itself a data frame of boxes for that input. It has the same shape that anonymize_video takes: x, y, width, height and an optional per-box color. An optional output column names the destination. When it is absent, the function derives one per row. It appends _anonymized to each input's basename and keeps the input's extension (e.g. clip.mkv becomes clip_anonymized.mkv). Two rows naming the same output path are refused before any row runs. That is a path repeated in the output column, or a repeated input when there is no output column. Four encoding arguments may also appear as a column: color, video_codec, audio_codec and pixel_format. Such a column overrides the corresponding argument on a per-row basis. Rows (or arguments) that omit the column fall back to the argument's value. In either codec column, NA leaves that row's codec unset. This is the column form of video_codec = NULL / audio_codec = NULL. In a color or pixel_format column NA is an error, because those have no unset state. An audio_stream column overrides the audio_stream argument per row, where NA keeps that row on every audio track. A numeric quality column overrides the quality argument per row (see quality). Any other columns are ignored.

color

A string naming the default fill color (FFmpeg color syntax) applied to every row. A color column in jobs, or a box that supplies its own color, overrides it. (default = "black")

video_codec

A string naming the output video codec applied to every row, unless jobs carries a video_codec column. In that column, NA in a cell leaves that row's codec unset. The default is "libx264". NULL emits no -codec:v and lets the output container's default encoder decide. For a .webm output, pass audio_codec = NULL too, because the default "copy" would otherwise carry a codec WebM cannot hold.

audio_codec

A string naming the output audio codec applied to every row, unless jobs carries an audio_codec column. In that column, NA in a cell leaves that row's codec unset. "copy" (default) stream-copies the audio through untouched. Name an encoder (e.g. "aac") when the source audio cannot be copied into the output container.

pixel_format

A string naming the output pixel format applied to every row, unless jobs carries a pixel_format column. (default = "yuv420p")

hardware

The encoder backend applied to every row. "none" (default) uses the software video_codec. "nvenc" gives NVIDIA GPU encoding (H.264, HEVC and AV1). "videotoolbox" gives Apple GPU encoding (H.264 and HEVC). Batch-wide (a machine property), not a per-row column; a hardware column in jobs is ignored. See has_hardware_encoder. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows. A call can also be wrong about a per-row value, for example a regions table that is missing a required column. The function refuses that call for the value first, whether or not this machine has the encoder.

fallback

A logical applied to every row. When a hardware other than "none" is requested but its encoder is unavailable, TRUE re-encodes with the software video_codec and a message. FALSE (default) aborts instead. It is batch-wide, not a per-row column. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default), applied to each row unless jobs carries a numeric quality column. In that column, NA leaves that row's encoder default in place, whatever the argument says. The value is the encoder's own rate-control value, passed through unchanged. Each cell is checked against the encoder its own row resolves to. A wrong cell is refused before any row runs, and the error names this function and the row. See anonymize_video() for the encoders, their flags and ranges, and the values it refuses.

audio_stream

The audio track to carry into each output, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The every-track family reads NULL as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each input's command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical passed to ffm_batch: anonymize in parallel with furrr (TRUE) or sequentially (FALSE, default). Parallelism follows the active future plan; TRUE under the default sequential plan runs one input at a time and warns. Set a plan first, e.g. future::plan(future::multisession).

...

Additional arguments forwarded to ffm_batch, such as verify, manifest, checksums, and progress.

Value

The tibble returned by ffm_batch: jobs with an added command column. When output was derived, it also has the resolved output column. When run = TRUE, it has a success column, plus any columns the forwarded arguments add, such as verified.

See Also

anonymize_video() for the single-input form. has_hardware_encoder() for the hardware argument. ffm_batch() for the batch runner and the arguments forwarded through .... standardize_video_batch() and segment_video_batch() for the other table-driven functions.

Other task functions: anonymize_video(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(
  input   = c(video, video),
  output  = c("a.mp4", "b.mp4"),
  regions = list(
    data.frame(x = 10, y = 10, width = 120, height = 90),
    data.frame(x = 200, y = 150, width = 80, height = 60)
  )
)
# run = FALSE compiles one command per input without calling FFmpeg
anonymize_video_batch(jobs, run = FALSE)

Audio track and audio input indices

Description

Two audio arguments in this package count different things: audio_stream and audio_input. Both count from 0, so 0 means the first one. This page explains which is which.

The glossary in vignette("tidymedia") explains media terms such as stream, container and codec.

Value

This page documents no function and returns no value. It explains two arguments the functions listed under See Also take. Each of those pages says what its own function returns.

The two indices

audio_stream counts the audio tracks of one input file. On extract_audio(), audio_stream = 1 is the second audio track of the file. Where that track sits among all the streams of the file does not matter. So audio_stream is not the index column of probe_audio(), which counts every stream, audio or not.

audio_input counts the input files of a function. The functions compare_videos() and picture_in_picture() combine several files into one output, so they must choose whose sound to keep. On these functions, audio_input = 1 is the second file. It says nothing about which track of that file is used.

You cannot work out one index from the other. So the package keeps two names, rather than one argument whose meaning depends on how many inputs a function takes.

What NULL means

audio_stream = NULL still selects audio. It does not mean "no audio". How much audio it selects depends on the function.

audio_input = NULL is different: it selects no audio at all, so the output has no audio. A silent output is the default for compare_videos() and picture_in_picture(). With several inputs, no choice of which one to hear is better than another.

The two arguments also fail in different ways when a number is too large. An audio_input that names an input you did not pass gives an R error, before FFmpeg runs. An audio_stream that names a track the input does not have gives an FFmpeg error. The reason is that the number of tracks is a fact about the file, not about the call.

In a ⁠_batch⁠ jobs table

On a ⁠_batch⁠ function, both arguments follow one rule. The argument you pass is the default, and a jobs column with the same name overrides it row by row.

This rule is about these two arguments only. The arguments hardware, parallel and two_pass apply to the whole batch, and the function reads no column for them.

If the column is absent, the argument applies to every row. If the column is present, each row uses its own cell. An NA cell means NULL for that row. It does not fall back to the argument. So audio_stream = 2 with an NA cell in an audio_stream column gives that row the NULL reading of its family, not track 2.

The name audio alone is not an index

The pipeline functions use audio for two things that are not counts:

The input index is called audio_input, so that its name says what it counts, as audio_stream does.

See Also

extract_audio, convert_audio and normalize_audio read NULL as the first audio track. separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web read it as every audio track. compare_videos() and picture_in_picture() take the input index. probe_audio() shows which audio tracks a file has.

Other audio selection functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()


Build a side-by-side comparison video

Description

Stack two or more videos into a single comparison video. The videos go side-by-side (direction = "horizontal") or one above the other (direction = "vertical"). This is a common need when reviewing annotations or before/after processing. Built on the stacking pipeline functions (ffm_hstack / ffm_vstack). The glossary in vignette("tidymedia") explains media terms such as codec, encoder and stream copy.

Usage

compare_videos(
  infiles,
  outfile,
  direction = c("horizontal", "vertical"),
  resize = TRUE,
  audio_input = NULL,
  video_codec = NULL,
  audio_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  run = TRUE
)

Arguments

infiles

A character vector of two or more video file paths. This function checks every path itself. A path that cannot be found or read aborts naming this function, and the error lists every such path. It is not reported against the internal builder that the path would otherwise reach.

outfile

A string giving the path to write the comparison video to.

direction

Either "horizontal" (side-by-side, the default) or "vertical" (stacked top to bottom).

resize

A logical indicating whether to resize the inputs to share an edge. Only supported for exactly two inputs. (default = TRUE)

audio_input

The input file whose audio to keep, as a number that counts from 0. 0 is the first file you pass and 1 is the second. This counts the function's inputs, not the audio tracks of one input. So it is a different index from audio_stream on the functions that take one input. NULL (default) selects no audio at all, so the output is silent. This differs from audio_stream = NULL, which still selects audio. An input number the call does not have gives an R error, before FFmpeg runs. See audio_stream. (default = NULL)

video_codec

A string naming the output video codec, or NULL (default) to leave it unset. Then the output container's default encoder is used, and the compiled command is the same as one that never named a codec.

audio_codec

A string naming the codec for the carried audio track. "copy" (default) stream-copies it through untouched. Name an encoder, such as "aac", to transcode it. NULL leaves the codec unset, so the output container's default encoder is used. When audio_input is NULL, no audio reaches the output, so nothing is emitted. Naming an encoder in that case is an error.

hardware

The encoder backend. "none" (default) uses the software video_codec. "nvenc" uses NVIDIA GPU encoding (H.264, HEVC and AV1), and "videotoolbox" uses Apple GPU encoding (H.264 and HEVC). A backend uses its own encoder for the family of video_codec. For example, "libx264" becomes "h264_nvenc" or "h264_videotoolbox". With the default video_codec = NULL, the H.264 family is assumed. So a non-H.264 container, such as .webm, needs an explicit HEVC- or AV1-family video_codec (AV1 only under "nvenc"). See has_hardware_encoder for availability and its caveats. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE encodes in software with a message. FALSE (default) aborts instead. With video_codec = NULL, the fallback leaves the codec unset rather than picking one, so the codec never changes silently. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default) to leave the encoder's own default in place. It is the encoder's own rate-control value, passed through unchanged. libx264 and libx265 read it as -crf (0 to 51). The nvenc encoders read it as -cq (0 to 51), and the videotoolbox encoders as -q:v (1 to 100). Each scale is its own: the same number means something different on each encoder. A value outside the encoder's range is refused. An encoder outside those seven, such as libvpx-vp9, is refused with quality set. So is a video_codec of "copy", or of NULL under hardware = "none". When fallback = TRUE falls back to software, the value is dropped and the message says so, because it belonged to the hardware encoder's scale.

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Details

By default the two inputs are resized to share an edge (equal heights for a horizontal stack, equal widths for a vertical one). Resizing currently supports exactly two inputs, so pass resize = FALSE to compare more. Audio is dropped unless audio_input names an input to carry; a carried track is stream-copied unless audio_codec names an encoder.

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_hstack() and ffm_vstack(), the pipeline functions it wraps; has_hardware_encoder() for the hardware argument; picture_in_picture() for insetting instead of stacking.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
compare_videos(c(video, video), "compare.mp4", run = FALSE)

Build Many Comparison Videos From a Jobs Table

Description

Stack videos side by side for many outputs from a single jobs tibble. This is the batch (table-driven) form of compare_videos(), for when you have more than one comparison to produce. Each row carries an inputs list-column (each cell two or more video paths) plus an output column. This is a thin wrapper over ffm_batch: one reproducible stacking command per row, sharing the pipeline with compare_videos(). The glossary in vignette("tidymedia") explains media terms such as codec, encoder and stream copy.

Usage

compare_videos_batch(
  jobs,
  direction = c("horizontal", "vertical"),
  resize = TRUE,
  audio_input = NULL,
  video_codec = NULL,
  audio_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per output and (at least) an inputs list-column and an output column (destination path). Each inputs cell is a character vector of two or more video paths. Optional direction, resize, audio_input, video_codec, and audio_codec columns override the like-named arguments per row (a row omitting one falls back to the argument). In an audio_input column, NA means "drop audio", the column's way of writing the scalar's NULL. In a video_codec or audio_codec column, it means "leave the codec unset". A numeric quality column overrides the quality argument per row (see quality). Two rows given the same output path are refused before any row runs; other columns are ignored.

direction, resize

Defaults applied to every row lacking the corresponding column. direction is "horizontal" (the default) or "vertical"; a direction column is held to the same two values, per row. See compare_videos() for their fuller meaning.

audio_input

The input file whose audio to keep, as a number that counts from 0. 0 is the first file you pass and 1 is the second. This counts the function's inputs, not the audio tracks of one input. So it is a different index from audio_stream on the functions that take one input. NULL (default) selects no audio at all, so the output is silent. This differs from audio_stream = NULL, which still selects audio. An input number the call does not have gives an R error, before FFmpeg runs. Without an audio_input column, the argument applies to every row. An NA cell in that column means NULL for that row, so that output has no audio. Each row's value is validated against that row's input count. See audio_stream. (default = NULL)

video_codec

A string naming the output video codec, applied to every row lacking a video_codec column. NULL (default) leaves it unset, so each output keeps its container's default encoder.

audio_codec

A string naming the codec for the carried audio track, applied to every row lacking an audio_codec column. "copy" (default) stream-copies it. Name an encoder to re-encode it, or NULL to leave the codec unset. A row carrying no audio emits no -codec:a, and naming an encoder on such a row is an error.

hardware, fallback

The encoder backend and its fallback behavior, applied to the whole batch. They are a property of the machine, not of a row, so neither is read as a jobs column. See compare_videos(). Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows. A call can also contradict itself by naming an audio_codec with no audio carried into the output. Such a call is refused for the contradiction first, whether or not this machine has the encoder. A per-row value error likewise reports ahead of the encoder check. Examples are an audio_input index past that row's input count, and a direction outside the two accepted values. A value error and a contradiction resolve the same way whether the value arrived as an argument or in a jobs column. The contradiction reports first.

quality

A number, or NULL (default), applied to each row unless jobs carries a numeric quality column. In that column, NA leaves that row's encoder default in place, whatever the argument says. The value is the encoder's own rate-control value, passed through unchanged. Each cell is checked against the encoder its own row resolves to. A wrong cell is refused before any row runs, and the error names this function and the row. See compare_videos() for the encoders, their flags and ranges, and the values it refuses.

run

A logical: run each command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical: process the jobs in parallel with furrr (TRUE) or one at a time (FALSE, default). See ffm_batch for the future plan requirement.

...

Additional arguments forwarded to ffm_batch (e.g. verify, manifest, progress).

Value

The jobs tibble with an added command column. When run = TRUE, it also has a success column, plus verified or a provenance manifest, each when requested through .... See ffm_batch.

See Also

compare_videos(), the one-output function it wraps; ffm_batch(), the batch runner; has_hardware_encoder() for the hardware argument. concatenate_videos_batch() and picture_in_picture_batch(), the other batch functions that take several inputs per row.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(inputs = list(c(video, video)), output = "compare.mp4")
compare_videos_batch(jobs, run = FALSE)

Combine video files using the concat demuxer

Description

Combine multiple video files one after another without needing to re-encode them by using the concat demuxer. This will be much faster than re-encoding but requires that the files have the same parameters (width, height, etc.) and formats/codecs. To concatenate videos using re-encoding, see the concat video filter. The glossary in vignette("tidymedia") explains media terms such as codec and re-encode.

Usage

concatenate_videos(infiles, outfile, run = TRUE)

Arguments

infiles

A character vector containing the file paths to video files. This function checks every path itself. A path that cannot be found or read aborts naming this function, and the error lists every such path. It is not reported against the internal builder that the path would otherwise reach.

outfile

A string containing the desired file path to write the new, concatenated video file to.

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_concat(), the pipeline function it wraps.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
concatenate_videos(c(video, video), "joined.mp4", run = FALSE)

Concatenate Many Videos From a Jobs Table

Description

Join clips end to end for many outputs from a single jobs tibble. This is the batch (table-driven) form of concatenate_videos(), for when you have more than one concatenation to produce. Unlike the single-input batch functions, each row's inputs are many. So jobs carries an inputs list-column (each cell a character vector of source paths) plus an output column. This is a thin wrapper over ffm_batch: one reproducible concat-demuxer command per row, sharing the copy + map-0 pipeline with concatenate_videos().

Usage

concatenate_videos_batch(jobs, run = TRUE, parallel = FALSE, ...)

Arguments

jobs

A data frame with one row per output and (at least) an inputs list-column and an output column (destination path). Each inputs cell is a character vector of the source paths to join, in order. An output column is required; this function derives no destination. Two rows given the same output path are refused before any row runs. Any other columns are ignored.

run

A logical: run each command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical: process the jobs in parallel with furrr (TRUE) or one at a time (FALSE, default). See ffm_batch for the future plan requirement.

...

Additional arguments forwarded to ffm_batch (e.g. verify, manifest, progress).

Value

The jobs tibble with an added command column. When run = TRUE, it also has a success column, plus verified or a provenance manifest, each when requested through .... See ffm_batch.

See Also

concatenate_videos(), the one-output function it wraps; ffm_batch(), the batch runner; compare_videos_batch() and picture_in_picture_batch(), the other batch functions that take several inputs per row.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(inputs = list(c(video, video)), output = "joined.mp4")
concatenate_videos_batch(jobs, run = FALSE)

Extract or convert a media file's audio track

Description

Write the audio stream of infile into outfile. By default (audio_codec = NULL), the output format follows the outfile file extension, at the highest VBR quality (-q:a 0). For example, an .mp3 extension gives an MP3. Pass audio_codec to set the output audio codec yourself, whatever the extension is. The glossary in vignette("tidymedia") explains media terms such as codec and stream.

Usage

convert_audio(
  infile,
  outfile,
  audio_codec = NULL,
  audio_stream = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a media file.

outfile

A string containing the path of the audio file to write.

audio_codec

An optional string naming the output audio codec (e.g. "libmp3lame", "aac", "flac"), passed to FFmpeg's -c:a. When NULL (default), FFmpeg infers the codec from the outfile extension and encodes at the highest VBR quality. On the other task functions, NULL means "leave the codec unset". Here NULL does not leave the codec unset. NULL selects -q:a 0.

audio_stream

The audio track to take, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) takes the first audio track. The first-track family reads NULL this way: extract_audio, convert_audio and normalize_audio, and their _batch forms. The every-track family reads it as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Details

When infile has more than one audio track, audio_stream names which one to take. With no audio_stream, the function takes the first one.

When no audio_stream is named and the input has tracks that the output will not carry, the function warns. The check costs one FFprobe call per distinct input, which is one call here, because this function takes a single infile. The warning is given when FFprobe is available and the input can be probed. Otherwise the check is skipped silently. It never runs under run = FALSE, and never changes the compiled command. Suppress it by naming a track with audio_stream, or by class with suppressWarnings(classes = "tidymedia_dropped_audio").

To switch the check off and skip its FFprobe call, use options(tidymedia.check_tracks = FALSE) for the session. Use withr::local_options(tidymedia.check_tracks = FALSE) for the rest of one function.

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_codec() and ffm_map(), the pipeline functions it wraps. extract_audio() to copy audio without re-encoding. convert_audio_batch() for the many-file form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
convert_audio(video, "audio.mp3", run = FALSE)
convert_audio(video, "audio.m4a", audio_codec = "aac", run = FALSE)
# Convert the second audio track instead of the first
convert_audio(video, "audio.mp3", audio_stream = 1, run = FALSE)

Convert the Audio of Many Files From a Jobs Table

Description

Extract or re-encode the audio track of many input files, using one jobs table. This is the batch form of convert_audio(), for when you have more than one file. Each row is one input. The input and output columns are required. The function is a thin wrapper over ffm_batch. It builds one reproducible command for each input. Each command uses the same audio steps as convert_audio(), and the function checks each audio_codec value in the same way. The glossary in vignette("tidymedia") explains media terms such as codec and stream.

Usage

convert_audio_batch(
  jobs,
  audio_codec = NULL,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input. It needs at least an input column (source path) and an output column (destination path). The output column is required. The function cannot name an audio destination for you, because its extension picks the output format. An optional audio_codec column overrides the audio_codec argument per row. There, NA means "use the highest-VBR-quality default". Rows without a value use the argument. An optional audio_stream column overrides the audio_stream argument per row in the same way, and NA keeps that row on the first audio track. The function refuses two rows with the same output path, before any row runs. The function ignores any other columns, with one exception. A format column is an error, not a silent no-op. The package retired that column with the argument of the same name.

audio_codec

The output audio codec applied to every row, unless jobs has an audio_codec column. With NULL (default), FFmpeg infers the codec from each output extension, at the highest VBR quality. Name a codec (e.g. "aac", "flac") to set -c:a.

audio_stream

The audio track to take, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) takes the first audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The first-track family reads NULL as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The every-track family reads it as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical: process the jobs in parallel with furrr (TRUE) or one at a time (FALSE, default). See ffm_batch for the future plan requirement.

...

Additional arguments forwarded to ffm_batch (e.g. verify, manifest, progress).

Details

When a row names no audio_stream and its input has tracks that the output will not carry, the function warns once for the whole batch. The warning names every affected row. The check costs one FFprobe call per distinct input it has to probe. A repeated input is probed once, and a row that names a track is not probed at all. The warning is given when FFprobe is available and the input can be probed. Otherwise the check is skipped silently. Those probes run one at a time, before any row starts, so parallel does not reach them. A sweep long enough to look like a hang reports its progress. The check never runs under run = FALSE, never changes any compiled command, and is skipped entirely when every row names a track. Suppress it by class with suppressWarnings(classes = "tidymedia_dropped_audio").

To switch the check off and skip the whole sweep, use options(tidymedia.check_tracks = FALSE) for the session. Use withr::local_options(tidymedia.check_tracks = FALSE) for the rest of one function.

Value

The jobs tibble with an added command column. When run = TRUE, it also has a success column, plus verified or a provenance manifest, each when requested through .... See ffm_batch.

See Also

convert_audio(), the single-input form it wraps. ffm_batch(), the batch runner. extract_audio_batch() to stream-copy audio in batch.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(input = c(video, video), output = c("a.mp3", "b.mp3"))
convert_audio_batch(jobs, run = FALSE)

Crop a video to a rectangular region

Description

Crop a video to a rectangular region. The glossary in vignette("tidymedia") explains media terms such as codec, container and stream copy.

Usage

crop_video(
  infile,
  outfile,
  width,
  height,
  x = "(in_w-out_w)/2",
  y = "(in_h-out_h)/2",
  video_codec = NULL,
  audio_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a video file.

outfile

A string containing the path of the video file to write.

width

The width of the output video, in pixels.

height

The height of the output video, in pixels.

x

The horizontal offset, in pixels, of the left edge of the crop. (default = centered)

y

The vertical offset, in pixels, of the top edge of the crop. (default = centered)

video_codec

A string naming the output video codec, or NULL (default) to leave it unset. Then the output container's default encoder is used, and the compiled command is the same as one that never named a codec.

audio_codec

A string naming the output audio codec. "copy" (default) stream-copies the audio through untouched. Name an encoder, such as "aac", to transcode it. NULL leaves the codec unset, so the output container's default encoder is used. Stream-copying fails if the output container cannot hold the source audio codec, for example FLAC in .mp4. In that case, name an encoder.

hardware

The encoder backend. "none" (default) uses the software video_codec. "nvenc" uses NVIDIA GPU encoding (H.264, HEVC and AV1), and "videotoolbox" uses Apple GPU encoding (H.264 and HEVC). A backend uses its own encoder for the family of video_codec. For example, "libx264" becomes "h264_nvenc" or "h264_videotoolbox". With the default video_codec = NULL, the H.264 family is assumed. So a non-H.264 container, such as .webm, needs an explicit HEVC- or AV1-family video_codec (AV1 only under "nvenc"). See has_hardware_encoder for availability and its caveats. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE encodes in software with a message. FALSE (default) aborts instead. With video_codec = NULL, the fallback leaves the codec unset rather than picking one, so the codec never changes silently. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default) to leave the encoder's own default in place. It is the encoder's own rate-control value, passed through unchanged. libx264 and libx265 read it as -crf (0 to 51). The nvenc encoders read it as -cq (0 to 51), and the videotoolbox encoders as -q:v (1 to 100). Each scale is its own: the same number means something different on each encoder. A value outside the encoder's range is refused. An encoder outside those seven, such as libvpx-vp9, is refused with quality set. So is a video_codec of "copy", or of NULL under hardware = "none". When fallback = TRUE falls back to software, the value is dropped and the message says so, because it belonged to the hardware encoder's scale.

audio_stream

The audio track to carry into the output, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. The every-track family reads NULL this way: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_crop(), the pipeline function it wraps; has_hardware_encoder() for the hardware toggle; crop_video_batch() for the many-file form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
crop_video(video, "cropped.mp4", width = 160, height = 120, run = FALSE)

Crop Many Videos From a Jobs Table

Description

Crop many videos to a rectangular region, using one jobs table. This is the batch form of crop_video(), for when you have more than one file. Each row is one input. The function is a thin wrapper over ffm_batch. It builds one reproducible command for each input, with the same crop steps as crop_video(). This function checks each row's crop size and position before any command runs. So a bad cell is refused with an error that names this function. The glossary in vignette("tidymedia") explains media terms such as codec, container and stream copy.

Usage

crop_video_batch(
  jobs,
  width = NULL,
  height = NULL,
  x = "(in_w-out_w)/2",
  y = "(in_h-out_h)/2",
  video_codec = NULL,
  audio_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input. It needs at least an input column, the source path. An optional output column names the destination. Without it, each row's output name adds _cropped to the input's base name and keeps its extension. For example, clip.mp4 becomes clip_cropped.mp4. A width, height, x or y column overrides that argument for each row. A dimension with no column uses the argument. A video_codec column overrides that argument for each row, and NA leaves the codec unset. That is the column form of the argument's NULL. An audio_codec column works the same way. An audio_stream column overrides that argument for each row, and NA keeps every audio track. That is the column form of that argument's NULL. Two rows with the same destination path are refused before any row runs. That happens with a repeated output, or with a repeated input when there is no output column. A numeric quality column overrides the quality argument per row (see quality). Any other columns are ignored.

width, height

The output crop size in pixels, for every row unless jobs has a column of the same name. Each is required: pass it as an argument or as a column. There is no default crop size.

x, y

The offset in pixels of the crop's left and top edge, for every row unless jobs has a column of the same name. The default centers the crop.

video_codec

A string naming the output video codec, applied to every row lacking a video_codec column. NULL (default) leaves it unset, so each output keeps its container's default encoder.

audio_codec

A string naming the output audio codec, for every row when jobs has no audio_codec column. "copy" (default) stream-copies the audio. Name an encoder to transcode it. NULL leaves the codec unset, so each output keeps its container's default encoder.

hardware, fallback

The encoder backend and its fallback behavior, applied to the whole batch. They are a property of the machine, not of a row, so neither is read as a jobs column. See crop_video(). Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows. A call can also have a per-row width or height that is neither a positive number nor an FFmpeg expression. Such a call is refused for the value first, whether or not this machine has the encoder.

quality

A number, or NULL (default), applied to each row unless jobs carries a numeric quality column. In that column, NA leaves that row's encoder default in place, whatever the argument says. The value is the encoder's own rate-control value, passed through unchanged. Each cell is checked against the encoder its own row resolves to. A wrong cell is refused before any row runs, and the error names this function and the row. See crop_video() for the encoders, their flags and ranges, and the values it refuses.

audio_stream

The audio track to carry into each output, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The every-track family reads NULL as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical: process the jobs in parallel with furrr (TRUE) or one at a time (FALSE, default). See ffm_batch for the future plan requirement.

...

Additional arguments forwarded to ffm_batch (e.g. verify, manifest, progress).

Value

The jobs tibble with an added command column. When run = TRUE, it also has a success column, plus verified or a provenance manifest, each when requested through .... See ffm_batch.

See Also

crop_video(), the single-input form it wraps; ffm_batch(), the batch runner; has_hardware_encoder() for the hardware toggle; standardize_video_batch() to re-encode in batch.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(input = c(video, video), output = c("a.mp4", "b.mp4"),
                       width = c(160, 80), height = c(120, 60))
crop_video_batch(jobs, run = FALSE)

Extract the audio stream from a media file

Description

Take one audio track out of infile, and drop the video. When the input has more than one audio track, audio_stream names which one to take. With no audio_stream, the function takes the first audio track. The glossary in vignette("tidymedia") explains media terms such as codec, container and stream copy.

Usage

extract_audio(
  infile,
  outfile,
  audio_codec = "copy",
  audio_stream = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a media file.

outfile

A string containing the path of the audio file to write.

audio_codec

A string naming the audio codec for the output stream. The default "copy" copies the stream into the new container without re-encoding. NULL writes no -codec:a, so the output container's default encoder decides. That is useful when FFmpeg cannot copy the source codec into the extension you asked for.

audio_stream

The audio track to take, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) takes the first audio track. The first-track family reads NULL this way: extract_audio, convert_audio and normalize_audio, and their _batch forms. The every-track family reads it as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Details

When no audio_stream is named and the input has tracks that the output will not carry, the function warns. The check costs one FFprobe call per distinct input, which is one call here, because this function takes a single infile. The warning is given when FFprobe is available and the input can be probed. Otherwise the check is skipped silently. It never runs under run = FALSE, and never changes the compiled command. Suppress it by naming a track with audio_stream, or by class with suppressWarnings(classes = "tidymedia_dropped_audio").

To switch the check off and skip its FFprobe call, use options(tidymedia.check_tracks = FALSE) for the session. Use withr::local_options(tidymedia.check_tracks = FALSE) for the rest of one function.

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_drop() and ffm_codec(), the pipeline functions it wraps. convert_audio() to re-encode the extracted audio. extract_audio_batch() for the many-file form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
extract_audio(video, "audio.aac", run = FALSE)
# Take the second audio track instead of the first
extract_audio(video, "audio.aac", audio_stream = 1, run = FALSE)

Extract Audio From Many Files From a Jobs Table

Description

Take the audio track out of many input files, using one jobs table. This is the batch form of extract_audio(), for when you have more than one file. Each row is one input. The input and output columns are required. The function is a thin wrapper over ffm_batch. It builds one reproducible command for each input, with the same steps as extract_audio(): select the audio track and drop the video. The glossary in vignette("tidymedia") explains media terms such as codec, container and stream copy.

Usage

extract_audio_batch(
  jobs,
  audio_codec = "copy",
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input. It needs at least an input column (source path) and an output column (destination path). The output column is required. Unlike the video batch functions, this function cannot name an audio destination for you, because the extension is the instruction. The extension picks the container, and with audio_codec = "copy" it must match the source codec. An optional audio_codec column overrides the audio_codec argument per row. Rows without a value use the argument. NA in a cell leaves that row's codec unset, which is the column form of audio_codec = NULL. An optional audio_stream column overrides the audio_stream argument per row in the same way, and NA keeps that row on the first audio track. The function refuses two rows with the same output path, before any row runs. The function ignores any other columns.

audio_codec

The audio codec applied to every row, unless jobs has an audio_codec column. In that column, NA in a cell leaves that row's codec unset. "copy" (default) copies the audio stream with no quality loss. Name an encoder (e.g. "aac") to re-encode. Or pass NULL to write no -codec:a, so the output container's default encoder decides.

audio_stream

The audio track to take, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) takes the first audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The first-track family reads NULL as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The every-track family reads it as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical: process the jobs in parallel with furrr (TRUE) or one at a time (FALSE, default). See ffm_batch for the future plan requirement.

...

Additional arguments forwarded to ffm_batch (e.g. verify, manifest, progress).

Details

When a row names no audio_stream and its input has tracks that the output will not carry, the function warns once for the whole batch. The warning names every affected row. The check costs one FFprobe call per distinct input it has to probe. A repeated input is probed once, and a row that names a track is not probed at all. The warning is given when FFprobe is available and the input can be probed. Otherwise the check is skipped silently. Those probes run one at a time, before any row starts, so parallel does not reach them. A sweep long enough to look like a hang reports its progress. The check never runs under run = FALSE, never changes any compiled command, and is skipped entirely when every row names a track. Suppress it by class with suppressWarnings(classes = "tidymedia_dropped_audio").

To switch the check off and skip the whole sweep, use options(tidymedia.check_tracks = FALSE) for the session. Use withr::local_options(tidymedia.check_tracks = FALSE) for the rest of one function.

Value

The jobs tibble with an added command column. When run = TRUE, it also has a success column, plus verified or a provenance manifest, each when requested through .... See ffm_batch.

See Also

extract_audio(), the single-input form it wraps. ffm_batch(), the batch runner. convert_audio_batch() to re-encode audio in batch.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(input = c(video, video), output = c("a.aac", "b.aac"))
extract_audio_batch(jobs, run = FALSE)

Extract a single frame from a video

Description

Save one frame of a video to an image file, selected either by timestamp or by frame number. Provide exactly one of timestamp or frame.

Usage

extract_frame(infile, outfile, timestamp = NULL, frame = NULL, run = TRUE)

Arguments

infile

A string containing the path to a video file.

outfile

A string containing the path of the image file to write.

timestamp

Either a number of seconds, a time-duration-syntax string, or NULL. Provide exactly one of timestamp or frame.

frame

Either an integerish frame number or NULL. Provide exactly one of timestamp or frame.

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_seek(), the pipeline function it uses to get the frame. extract_frame_batch() for the many-file (batch) form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# run = FALSE returns the reproducible command instead of executing it
extract_frame(video, "frame.png", timestamp = 0.5, run = FALSE)

Extract Still Frames From Many Videos From a Jobs Table

Description

Save one still image for each row, across many input files, using one jobs table. This is the batch form of extract_frame(), for when your frames come from more than one input. Each row is one frame. The required columns name its source and the moment to capture. The function is a thin wrapper over ffm_batch. It builds one reproducible command for each frame. The glossary in vignette("tidymedia") explains media terms such as frame rate.

Usage

extract_frame_batch(jobs, format = "png", run = TRUE, parallel = FALSE, ...)

Arguments

jobs

A data frame with one row per frame. It needs at least an input column (source path). It also needs exactly one of a timestamp column and a frame column. A timestamp holds seconds, or FFmpeg time-duration strings. A frame holds whole frame numbers. The function converts each one to a timestamp with the input's frame rate, as extract_frame does. An optional output column names the destination image. When it is absent, the function derives one per row by appending _<n>.<format> to each input's basename. The frame number restarts at 1 for each input file. The function refuses two rows whose destination is the same path, before any row runs. That covers a repeated output, and two derived names that match. For example, clip.mp4 and clip.mkv both give clip_1.png. The function ignores any other columns.

format

A string giving the image file extension used when the function derives output. The function ignores it when jobs has an output column. (default = "png")

run

A logical: run each frame's command through FFmpeg (TRUE, default) or only build the commands for inspection (FALSE).

parallel

A logical passed to ffm_batch: save frames in parallel with furrr (TRUE) or one after another (FALSE, default). Parallel work follows the active future plan. TRUE under the default sequential plan runs one frame at a time and warns.

...

Additional arguments forwarded to ffm_batch, such as verify, manifest, checksums, and progress.

Value

The tibble returned by ffm_batch: jobs with an added command column. When output was derived, it also has the resolved output column. When run = TRUE, it has a success column, plus any columns the forwarded arguments add, such as verified.

References

https://ffmpeg.org/ffmpeg-utils.html#time-duration-syntax

See Also

extract_frame() for the single-frame form. ffm_batch() for the batch runner and the arguments passed on through .... segment_video_batch() for the batch function that cuts segments.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(
  input     = c(video, video),
  output    = c("a.png", "b.png"),
  timestamp = c(0.25, 0.75)
)
# run = FALSE compiles one command per frame without calling FFmpeg
extract_frame_batch(jobs, run = FALSE)

Run an FFmpeg Pipeline Over Many Files

Description

Apply a pipeline-building function to every row of a jobs table and compile (and optionally run) the resulting FFmpeg command for each. This is the package's main batch function. It gives one reproducible compiled command per job, collected back into a tibble.

Usage

ffm_batch(
  jobs,
  .f,
  ...,
  run = TRUE,
  parallel = FALSE,
  verify = NULL,
  progress = FALSE,
  manifest = FALSE,
  checksums = FALSE
)

Arguments

jobs

A data frame with one row per job. Its column names are the arguments passed to .f.

.f

A function that takes a job's columns (by name) and returns an ffm pipeline object.

...

Additional arguments passed on to every call of .f.

run

A logical: run each compiled command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE, a dry run).

parallel

A logical: map over jobs in parallel with furrr (TRUE) or sequentially (FALSE, default). Parallel runs follow the future plan that you set. With TRUE and the default sequential plan, jobs still run one at a time, and you get a warning. Set a plan first, for example future::plan(future::multisession).

verify

An optional output check applied to each job (only when run = TRUE). Give a named list of expected properties, or a function. A list, for example list(width = 1920), applies the same checks to every job. A function takes the job columns like .f (called pmap-style) and returns such a list for each job. Each job's output is passed to verify_media. Unlike ffm_run, a failed check is recorded, and does not stop the call. Adds a logical verified column (all checks passed), NA for jobs that did not run successfully.

progress

A logical: display a cli progress bar as the jobs run (TRUE) or run quietly (FALSE, default). Only applies when run = TRUE; safe (a no-op animation) in non-interactive sessions.

manifest

A logical. When TRUE (and run = TRUE), the batch records a provenance manifest and attaches it to the result. The manifest has each job's command, the FFmpeg and FFprobe versions, a timestamp and the output size. Read it with ffm_manifest. (default = FALSE)

checksums

A logical: when TRUE, the manifest also captures md5 checksums of each job's input(s) and output. Ignored unless manifest = TRUE. (default = FALSE)

Details

Each column of jobs is passed by name to .f (as purrr::pmap() does), so a job table with columns input, output and start calls .f(input = ..., output = ..., start = ...). .f must return a pipeline (see ffm_files). Give .f a ... argument if jobs carries columns it does not use.

Two jobs whose pipelines write to the same output path are refused before any job runs, under run = FALSE as well as run = TRUE. Paths are compared exactly as written. An output that writes no file may repeat. Such outputs are - (standard output), a pipe: URL, and an output whose last -f option is -f null, as ffm_output_options("-f null") gives.

with_timeout() explains how to limit how long R waits for each program in a job, and what happens when a program reaches the limit.

Value

jobs as a tibble with an added command column, which holds the compiled FFmpeg command for each job. When run = TRUE, it also has a logical success column. When verify is supplied, it also has a verified column. When manifest = TRUE, a provenance manifest is attached as an attribute; read it with ffm_manifest.

See Also

segment_video(), which is built on ffm_batch(); verify_media() for the verification spec and ffm_manifest() for the provenance manifest.

Other pipeline functions: ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(
  input  = c(video, video),
  output = c("a.mp3", "b.mp3")
)
# run = FALSE compiles one command per job without calling FFmpeg
ffm_batch(jobs, run = FALSE, .f = function(input, output, ...) {
  ffm_files(input, output) |>
    ffm_drop("video") |>
    ffm_codec(audio = "libmp3lame")
})

Set Codecs in an FFmpeg Pipeline

Description

Set the audio codec, the video codec, or both, for the output file. Use ffmpeg_codecs() to see a list of the codecs in your FFmpeg version. The glossary in vignette("tidymedia") explains media terms such as codec and stream copy.

Usage

ffm_codec(object, audio = NULL, video = NULL)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

audio

A string that names the audio codec, or NULL to set only the video codec. The default is NULL. See audio_stream for the two things that the name audio means in the pipeline functions, and for the input index audio_input.

video

A string that names the video codec, or NULL to set only the audio codec. The default is NULL.

Value

object with an added instruction to change the codecs.

References

https://ffmpeg.org/ffmpeg-codecs.html

See Also

ffm_copy(), the shortcut for stream copy, ffmpeg_codecs() to list the codecs you can use, and standardize_video(), a task function built on it.

Other pipeline functions: ffm_batch(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_codec(video = "libx264", audio = "aac") |>
  ffm_compile()

Compile the tidymedia pipeline into an FFmpeg command

Description

Compile all the instructions into one string, the FFmpeg command that runs them.

Usage

ffm_compile(object)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

Value

A string with the FFmpeg command that carries out all the instructions in the tidymedia pipeline.

See Also

ffm_run() to compile and run in one step, and ffm_batch() to compile over many files.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# ffm_compile() returns the reproducible FFmpeg command as a string
ffm_files(video, "output.mp4") |>
  ffm_trim(start = 1, end = 5) |>
  ffm_crop(width = 160, height = 120) |>
  ffm_codec(video = "libx264") |>
  ffm_compile()

Concatenate Multiple Inputs in an FFmpeg Pipeline

Description

Join the pipeline's input files one after another with FFmpeg's concat demuxer. Like ffm_hstack, this is a pipeline function for several inputs. It uses stream copy, so it is fast and lossless. But every input must share the same parameters, such as codec, resolution and frame rate. The glossary in vignette("tidymedia") explains media terms such as codec, re-encode and stream copy.

Usage

ffm_concat(object)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files() with more than one input file.

Details

To join inputs with different parameters, you must re-encode with the concat filter. The package does not wrap that filter yet, so use ffmpeg.

The demuxer needs a list file that names the inputs. When you call ffm_concat(), it writes one to a temporary path and stores it in the pipeline, so the compiled command can refer to it. It also copies codecs and maps all streams, as ffm_copy would.

Value

object with an added instruction to concatenate the inputs.

See Also

concatenate_videos(), the task function built on this function.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Join two inputs end-to-end (they must share codec/resolution/frame rate)
ffm_files(c(video, video), "output.mp4") |>
  ffm_concat() |>
  ffm_compile()

Copy the codecs and map all streams

Description

Copy the audio, the video, or both, with stream copy and no re-encoding. It can also map all streams from the input. This is the fast, lossless path when you only need to put the streams in a new container or cut on keyframes. The glossary in vignette("tidymedia") explains media terms such as codec, container, keyframe and stream copy.

Usage

ffm_copy(object, audio = TRUE, video = TRUE, streams = TRUE)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

audio

A logical. TRUE (the default) copies the audio codec. See audio_stream for the two things that the name audio means in the pipeline functions, and for the input index audio_input.

video

A logical. TRUE (the default) copies the video codec.

streams

A logical. TRUE (the default) maps all streams from the input. It sets the mapping to the all-streams specifier "0", and does not add to it. So two ffm_copy() calls compile one -map "0", not two. If the pipeline already has a different mapping, ffm_copy() gives an error and does not discard that mapping silently. To keep the mapping you set, pass streams = FALSE. Or call ffm_copy() first, and then narrow the mapping with ffm_map(replace = TRUE).

Value

object with an added instruction to copy codecs, map all streams, or both.

See Also

ffm_codec() and ffm_map(), which ffm_copy() calls, and segment_video(), which uses it for fast copy cuts.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_copy() |>
  ffm_compile()

Crop Frames in an FFmpeg Pipeline

Description

Make the video's frames smaller by cropping them.

Usage

ffm_crop(object, width, height, x = "(in_w-out_w)/2", y = "(in_h-out_h)/2")

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

width

The width of the output video, in pixels. Give a positive real number or a string that contains an FFmpeg expression.

height

The height of the output video, in pixels. Give a positive real number or a string that contains an FFmpeg expression.

x

The horizontal position of the left edge of the output video, in pixels of the input video. Give a positive real number or a string that contains an FFmpeg expression. The default is "(in_w-out_w)/2".

y

The vertical position of the top edge of the output video, in pixels of the input video. Give a positive real number or a string that contains an FFmpeg expression. The default is "(in_h-out_h)/2".

Value

object with an added instruction to crop the frames.

References

https://ffmpeg.org/ffmpeg-filters.html#crop

See Also

ffm_scale() to resize instead of crop. crop_video() and format_for_web() are the task functions built on ffm_crop().

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Crop to a centered 160x120 region
ffm_files(video, "output.mp4") |>
  ffm_crop(width = 160, height = 120) |>
  ffm_compile()

Draw a Colored Box on the Videos in an FFmpeg Pipeline

Description

Add a video filter that draws a colored rectangle on the input video.

Usage

ffm_drawbox(
  object,
  x = 0,
  y = 0,
  width = "in_w",
  height = "in_h",
  color = "black",
  thickness = "fill"
)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

x

The horizontal position of the left edge of the box, in pixels of the input video. Give a nonnegative real number or a string that contains an FFmpeg expression. The default is 0.

y

The vertical position of the top edge of the box, in pixels of the input video. Give a nonnegative real number or a string that contains an FFmpeg expression. The default is 0.

width

The width of the box, in pixels. Give a positive real number or a string that contains an FFmpeg expression. The default is "in_w".

height

The height of the box, in pixels. Give a positive real number or a string that contains an FFmpeg expression. The default is "in_h".

color

A string with the color of the box, in FFmpeg color syntax. The reference link below explains that syntax. With the special value "invert", the box has the color of the video with inverted luma. The default is "black".

thickness

The thickness of the box edge, in pixels. The value "fill" draws a filled box. The default is "fill".

Value

object with an added instruction to apply the drawbox filter.

References

https://ffmpeg.org/ffmpeg-filters.html#drawbox

https://ffmpeg.org/ffmpeg-utils.html#color-syntax

See Also

anonymize_video(), the task function that uses ffm_drawbox() to fill regions.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Draw a filled red box covering the top-left quarter of the frame
ffm_files(video, "output.mp4") |>
  ffm_drawbox(width = "in_w/2", height = "in_h/2", color = "red") |>
  ffm_compile()

Drop Streams from an FFmpeg Pipeline

Description

Remove one or more streams from the media file. For example, remove the video, audio, subtitles or data stream from a media file. The glossary in vignette("tidymedia") explains media terms such as stream.

Usage

ffm_drop(object, streams = c("video", "audio", "subtitles", "data"))

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

streams

A character vector with one or more of these strings: "video", "audio", "subtitles" and "data".

Value

object with an added instruction to drop these streams from the output file when the pipeline runs.

See Also

extract_audio(), the task function that uses ffm_drop() to drop the video stream.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Drop the audio stream (keep video only)
ffm_files(video, "output.mp4") |>
  ffm_drop(streams = "audio") |>
  ffm_compile()

Specify Files in an FFmpeg Pipeline

Description

Start an FFmpeg pipeline by specifying input and output files.

Usage

ffm_files(input, output, overwrite = TRUE)

Arguments

input

A character vector of paths to the input media files of the pipeline. Give more than one path for stacking.

output

A string with the path of the output media file of the pipeline.

overwrite

A logical. If TRUE (the default), an output media file that already exists is overwritten.

Value

An FFmpeg pipeline object.

See Also

ffm_compile() to build the command and ffm_run() to run it. The task functions, such as standardize_video() and segment_video(), are built on the pipeline functions.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_compile()

Set the Frame Rate in an FFmpeg Pipeline

Description

Resample the video to a constant frame rate with FFmpeg's fps filter. The filter duplicates or drops frames as needed. It is added to the end of the video filters, like the other filters that take one input. The glossary in vignette("tidymedia") explains media terms such as frame rate.

Usage

ffm_fps(object, fps)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

fps

The target frame rate. Give a positive real number of frames per second, or a string that contains an FFmpeg frame rate expression. For example, "30000/1001" is the NTSC rate.

Value

object with an added instruction to resample the frame rate.

See Also

standardize_video(), the task function that uses ffm_fps() to set the frame rate.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_fps(fps = 30) |>
  ffm_compile()

Horizontally Stack Multiple Videos in an FFmpeg Pipeline

Description

Add a complex video filter that stacks several videos horizontally (side by side). It can also resize the videos to the same height.

Usage

ffm_hstack(object, shortest = FALSE, resize = FALSE)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

shortest

A logical that says whether to trim the duration of all videos to that of the shortest video. The default is FALSE.

resize

A logical that says whether to resize the input videos to the same height. Resizing takes longer, and for now it works only with two inputs. It fits both inputs to the same aspect ratio, so it assumes the inputs share one.

Value

object with an added instruction to stack the videos horizontally.

See Also

ffm_vstack() for vertical stacking, and compare_videos(), the task function built on both.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Stack two inputs side-by-side (pass more than one input to ffm_files())
ffm_files(c(video, video), "output.mp4") |>
  ffm_hstack() |>
  ffm_compile()

Build a Jobs Table From a Directory

Description

List the media files in a directory and return them as a jobs table for ffm_batch(). The table is a tibble with one row per file and an input column of full paths. Start a batch here, instead of with your own list.files() call.

Usage

ffm_jobs(directory, type, extension = NULL, recursive = FALSE)

Arguments

directory

A single string naming an existing directory.

type

The media category to list, one of "video", "audio" or "image". You must give it, because it has no default.

extension

An optional character vector of file extensions narrowing the search within type, with or without a leading dot ("mp4" and ".mp4" both work). Each must be one of the extensions type covers, and the error message lists them. NULL (the default) lists every extension of that type.

recursive

A logical: descend into subdirectories (TRUE) or list only the top level (FALSE, default).

Details

The table has only the input column. ffm_batch() passes every column of the jobs table to .f by name. So if .f has no argument for a column, and no ... argument, the batch stops with R's "unused argument" error.

Add the columns your pipeline needs with the usual data-frame tools. Some *_batch() task functions need an output column. Others need columns for their task, such as start and end. The examples below make an output column from input.

crop_video_batch() and extract_audio_batch() handle the other columns of the table as follows:

Value

A tibble with one row per matching file and one character column, input, with each file's full path. Files whose names start with a dot are left out. Rows are in the order list.files returns them.

Every row is a path that exists and is not a directory. A subdirectory whose own name ends in a listed extension is never a row. On macOS and Linux, a symbolic link whose target is gone is never a row either. Windows reports such a link as existing, so there it can still be a row. The call gives an error, instead of zero rows, when nothing matches. With recursive = TRUE the search follows a symbolic link to a directory, so a row can name a file outside directory.

The scanned extensions include .mka as audio and .ts as video. separate_audio_video() recommends .mka or .m4a for multi-track audio, and this function reads both as audio, so it lists a folder of that output. Not every container that can hold several audio streams is audio here. .ts, like .mp4 and .mkv, is video, so multi-track audio written to one of those is a row under type = "video". The name .ts also belongs to TypeScript source files, and this function reads names rather than file contents. A folder of TypeScript sources therefore comes back as video rows when you ask for type = "video".

See Also

ffm_batch(), which consumes the returned table.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

folder <- system.file("extdata", package = "tidymedia")
jobs <- ffm_jobs(folder, type = "video")
jobs

# Derive an output column, then hand the whole table to ffm_batch().
# Two inputs sharing a name (a.mp4 and a.mkv) would derive one output here;
# ffm_batch() refuses jobs that share an output before any of them runs.
jobs$output <- file.path(tempdir(), paste0(
  tools::file_path_sans_ext(basename(jobs$input)), ".mp3"
))
ffm_batch(jobs, run = FALSE, .f = function(input, output, ...) {
  ffm_files(input, output) |> ffm_drop("video")
})

Normalize Loudness in an FFmpeg Pipeline

Description

Add FFmpeg's loudnorm (EBU R128) audio filter. It normalizes the input's perceived loudness toward a target integrated loudness, true-peak ceiling and loudness range. The filter compiles to -af, or joins an existing audio filter chain in the order the filters were added. The glossary in vignette("tidymedia") explains media terms such as LUFS and true peak.

Usage

ffm_loudnorm(
  object,
  target_loudness = -23,
  true_peak = -1,
  loudness_range = 7,
  measured_i = NULL,
  measured_tp = NULL,
  measured_lra = NULL,
  measured_thresh = NULL,
  offset = NULL,
  linear = FALSE,
  print_format = NULL
)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

target_loudness

The target integrated loudness, in LUFS (a number in -70..-5). The default, -23, is the EBU R128 target.

true_peak

The maximum true peak, in dBTP (a number in -9..0). The default, -1, is the EBU R128 ceiling.

loudness_range

The target loudness range, in LU (a number in 1..50). The default is 7.

measured_i, measured_tp, measured_lra, measured_thresh

Measured input values from an earlier loudnorm analysis pass: integrated loudness, true peak, loudness range and threshold. Give them together for an accurate two-pass (linear) correction. Give these values and offset as one set, or give none of them. NULL, the default, gives single-pass dynamic normalization. These map to FFmpeg's measured_I, measured_TP, measured_LRA and measured_thresh options.

offset

The target_offset (offset gain) that the analysis pass reports. It is part of the measured set (see measured_i). The default is NULL.

linear

A logical. TRUE requests linear normalization (linear=true), which needs the measured values to hit the target precisely. FALSE (the default) leaves out the option, so the single-pass dynamic behavior does not change.

print_format

The format of the measurement report for an analysis pass: "json", "summary" or "none". NULL (the default) leaves out the option. Use "json" for an analysis pass that a program can parse.

Details

This is single-pass (dynamic) loudnorm. The pipeline stays one reproducible command, with no measurement pass. The defaults follow EBU Recommendation R 128 (2014): target_loudness = -23 LUFS and true_peak = -1 dBTP. Loudness is measured per ITU-R BS.1770-4. The default loudness_range = 7 is FFmpeg's own loudnorm default. EBU R128 does not prescribe a single value.

Two filters are added, not one. loudnorm is followed by asetnsamples, which regroups the filtered audio into frames of 4096 samples and does not pad the last one. Dynamic loudnorm resamples to 192 kHz and gives frames of 192000 samples. Some encoders accept whatever frame they are given, FLAC and Vorbis among them. Even those encoders refuse to open at all on frames of 192000 samples.

Value

object with an added instruction to normalize loudness.

References

EBU Recommendation R 128 (2014), Loudness normalisation and permitted maximum level of audio signals; ITU-R BS.1770-4. https://ffmpeg.org/ffmpeg-filters.html#loudnorm

See Also

normalize_audio(), the task function built on this filter.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_loudnorm() |>
  ffm_compile()

Read a Batch Provenance Manifest

Description

Retrieve the reproducibility manifest recorded by ffm_batch() when it was run with manifest = TRUE. The manifest is a tibble with one row per job. Each row has the compiled command and the FFmpeg and FFprobe versions used. It also has the time of the run, the input and output paths, and the output file size. When the batch ran with checksums = TRUE, each row also has md5 checksums of the input and output files. With the manifest, a batch run leaves a record that others can check.

Usage

ffm_manifest(x, path = NULL)

Arguments

x

A tibble returned by ffm_batch() with manifest = TRUE.

path

An optional file path. When supplied, the manifest is also written there as CSV (via utils::write.csv, no row names) and returned invisibly.

Value

The manifest tibble; invisibly when path is written.

See Also

ffm_batch(), which records the manifest.

Other verification functions: verify_media()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(input = video, output = tempfile(fileext = ".mp3"))
res <- ffm_batch(jobs, manifest = TRUE, .f = function(input, output, ...) {
  ffm_files(input, output) |> ffm_drop("video")
})
ffm_manifest(res)


Set the Stream Mapping in an FFmpeg Pipeline

Description

Choose which input streams go into the output, with FFmpeg's -map option. The default, "0", maps every stream from the first input. The glossary in vignette("tidymedia") explains media terms such as stream.

Usage

ffm_map(object, mapping = "0", replace = FALSE)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

mapping

A character vector of one or more stream specifiers. Each one adds one -map.

replace

A logical. TRUE discards any mapping already set on object. FALSE (the default) adds to it.

Details

mapping can be a character vector. Each element adds one -map, in the order given. For example, ffm_map(object, c("0:v", "0:a:1")) keeps the video and the second audio track of the input.

A second ffm_map() call adds to the maps already set. It does not replace them. Pass replace = TRUE to discard them instead. That is how you narrow the all-streams map that ffm_copy sets. Adding to that map puts the stream in the output twice, and does not select it.

ffm_map() is the only pipeline function that adds to earlier calls. Every other ffm_* function that sets a value, ffm_copy included, replaces it. ffm_map() is different because its arguments are partial choices that combine. For example, you keep the video, then name one audio track.

When the pipeline uses a function with several inputs, such as ffm_hstack, your mapping is added beside the automatic -map "[vout]" of the filtered stream. For example, ffm_map(object, "0:a") keeps the audio of the first input next to the stacked video.

Value

object with an added instruction to map streams.

See Also

ffm_copy(), which maps all streams, and separate_audio_video(), a task function built on ffm_map().

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_map(mapping = "0") |>
  ffm_compile()

# Keep the video and the second audio track only
ffm_files(video, "output.mkv") |>
  ffm_map(mapping = c("0:v", "0:a:1")) |>
  ffm_compile()

Add Raw Output Options to an FFmpeg Pipeline

Description

Add one or more raw FFmpeg output options to the pipeline, after any added before. Output options are the flags after the input and before the output file. Use this function for an option that has no pipeline function of its own. ffm_compile() still decides where the options go and how the rest of the command is quoted. So this is not the same as writing the command string yourself.

Usage

ffm_output_options(object, ...)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

...

One or more strings. Each string is a group of options separated by white space, for example "-q:v 1" or "-frames:v 1". They are added in the order given. When the command runs, each word between white space becomes one FFmpeg argument. So an option value must not contain spaces.

Value

object with the added output options.

See Also

ffmpeg(), the direct command that takes any FFmpeg arguments, and ffm_compile(), which places these options.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Extract a single frame by adding a raw output option
ffm_files(video, "frame.png") |>
  ffm_output_options("-frames:v 1") |>
  ffm_compile()

Overlay One Video on Another in an FFmpeg Pipeline

Description

Draw the second input (the overlay) on top of the first input (the main video) at position x and y. Like ffm_hstack, this is a pipeline function for several inputs. It forces the -filter_complex path and manages its own stream labels internally. It needs exactly two inputs. The first is the background, and the second is drawn over it. The glossary in vignette("tidymedia") explains media terms such as stream.

Usage

ffm_overlay(object, x = 0, y = 0, shortest = FALSE, scale = NULL)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files() with exactly two input files.

x

The horizontal position of the overlay's left edge, as a number of pixels or an FFmpeg expression. The default is 0.

y

The vertical position of the overlay's top edge, as a number of pixels or an FFmpeg expression. The default is 0.

shortest

A logical that says whether to end the output when the shorter input ends. The default is FALSE.

scale

An optional fraction (0 < scale <= 1). Before the overlay is drawn, it is resized to scale times the main video's width, and its aspect ratio is kept. NULL (the default) draws the overlay at its own size. When scale is set, overlay_w and overlay_h in x and y refer to the resized overlay.

Details

x and y accept plain numbers or FFmpeg overlay expressions. A plain number counts pixels from the top-left of the main video. In an expression, main_w and main_h are the main video's dimensions. overlay_w and overlay_h are the overlay's dimensions. For example, x = "main_w-overlay_w-16" puts the overlay 16 pixels from the right edge.

When scale is set, the overlay is first resized to a fraction of the main video's width, and its aspect ratio is kept. The task function picture_in_picture uses this resize. Otherwise, to resize the overlay yourself, filter it in a separate pipeline first.

Value

object with an added instruction to draw the second input on the first.

See Also

picture_in_picture(), the task function built on this function.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Draw the second input over the first, 16px in from the top-right corner
ffm_files(c(video, video), "output.mp4") |>
  ffm_overlay(x = "main_w-overlay_w-16", y = 16) |>
  ffm_compile()

Set the Pixel Format in an FFmpeg Pipeline

Description

Set the pixel format of the output with FFmpeg's -pix_fmt option. For example, use "yuv420p" for broad player compatibility. The glossary in vignette("tidymedia") explains media terms such as pixel format.

Usage

ffm_pixel_format(object, format)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

format

A string that names the pixel format of the output file.

Value

object with an added instruction to set the pixel format.

See Also

standardize_video() and format_for_web(), the task functions that use ffm_pixel_format() to set the pixel format.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_pixel_format("yuv420p") |>
  ffm_compile()

Run the FFmpeg Pipeline

Description

Compile the instructions in the pipeline and run them all through FFmpeg.

Usage

ffm_run(object, verify = NULL)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

verify

An optional named list of the properties you expect the output to have, for example list(width = 1920, video_codec = "h264"). It is passed to verify_media. After a successful run, the output is probed. If a check fails, ffm_run() gives an error with the failed checks. It also gives an error when FFmpeg exits non-zero. NULL (the default) skips the checks.

Value

FFmpeg's standard output as a character vector, returned invisibly. On a non-zero exit it has a status attribute. You call ffm_run() to write the output file, not for its return value. The pipeline runs as a vector of arguments and never through a shell. So paths with spaces or special characters are safe.

When FFmpeg exits non-zero

If FFmpeg refuses a run, ffm_run() gives an error of class tidymedia_ffmpeg_exit. A caller can catch a failed run without reading the error text:

tryCatch(
  ffm_run(pipeline),
  tidymedia_ffmpeg_exit = function(cnd) cnd$tm_status
)

The tm_status field is one integer, the exit status exactly as system2() reported it. If a signal stopped FFmpeg, the field holds the shell's number, 128 plus the signal number, unchanged. That number stands for the signal, not for a status FFmpeg chose to return.

Two other paths give this class and carry this field, so one handler covers all three:

Each of those two paths also gives a second, narrower class before this one. In the same order, they are tidymedia_loudnorm_no_measurement and tidymedia_multitrack_separation. Catch that class when you want only that failure.

Two related paths do not give this class, each for its own reason:

So tidymedia_loudnorm_no_measurement is the one class that covers the analysis pass in both forms.

See Also

ffm_compile() to get the command without running it, ffm_batch() to run many files, and verify_media() for the verify list.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
out <- tempfile(fileext = ".mp4")
ffm_files(video, out) |>
  ffm_scale(width = 160, height = 120) |>
  ffm_codec(video = "libx264") |>
  ffm_run(verify = list(width = 160, height = 120))


Scale (Resize) Frames in an FFmpeg Pipeline

Description

Scale (resize) the input video's frames to a width and height in pixels, or with an FFmpeg expression.

Usage

ffm_scale(object, width, height)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

width

The width of the output video, in pixels. Give a positive real number or a string that contains an FFmpeg expression.

height

The height of the output video, in pixels. Give a positive real number or a string that contains an FFmpeg expression.

Value

object with an added instruction to resize the frames.

See Also

ffm_crop() to crop instead of resize. standardize_video() is the task function built on ffm_scale().

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_seek(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_scale(width = 160, height = 120) |>
  ffm_compile()

Cut a Continuous Section from an FFmpeg Pipeline by Seeking

Description

Keep one continuous section of the input with FFmpeg's fast -ss and -to seek options. It does not use the trim filter of ffm_trim. Unlike the filter, seeking can use stream copy, so it is the tool for fast, lossless cuts. The glossary in vignette("tidymedia") explains media terms such as keyframe, re-encode and stream copy.

Usage

ffm_seek(object, start = NULL, end = NULL, reencode = TRUE)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

start

The start of the kept section, in seconds or in FFmpeg time duration syntax. NULL keeps the section from the beginning.

end

The end of the kept section, in seconds or in FFmpeg time duration syntax. NULL keeps the section to the end.

reencode

A logical. TRUE (the default) re-encodes for a frame-accurate cut. FALSE makes a fast seek that is safe to copy, and its cut points move to keyframes.

Details

The reencode argument trades accuracy against speed:

Value

object with an added instruction to cut the input by seeking.

References

https://ffmpeg.org/ffmpeg.html#Main-options

See Also

ffm_trim() for the filter that cuts, ffm_copy() for the fast copy path, and segment_video(), the task function built on it.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_trim(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Fast, lossless copy cut (snaps to keyframes)
ffm_files(video, "output.mp4") |>
  ffm_seek(start = 1, end = 5, reencode = FALSE) |>
  ffm_copy() |>
  ffm_compile()

Trim the Duration of the FFmpeg Pipeline

Description

Trim the input so that the output keeps one continuous part of the input. If start is NULL, the kept section starts at the beginning of the input. If both end and duration are NULL, the kept section ends at the end of the input. The glossary in vignette("tidymedia") explains media terms such as stream copy.

Usage

ffm_trim(
  object,
  start = NULL,
  end = NULL,
  duration = NULL,
  units = c("tds", "pts", "frame"),
  setpts = TRUE
)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

start

The time of the start of the kept section, given in units. The frame at this time is the first frame of the output.

end

The time of the first frame that is dropped, given in units. The frame just before it is the last frame of the output.

duration

The maximum duration of the output, given in time duration syntax.

units

A string that says how start and end are given: time duration syntax ("tds"), timebase units ("pts") or frame numbers ("frame"). The default is "tds".

setpts

A logical that says whether the output timestamps change to start at zero. If TRUE, a setpts filter is added after the trim.

Value

object with added instructions to trim the duration.

References

https://ffmpeg.org/ffmpeg-filters.html#trim

https://ffmpeg.org/ffmpeg-utils.html#time-duration-syntax

See Also

ffm_seek(), the faster cut by seeking, which can use stream copy. ffm_trim() is the filter that cuts on exact frames.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_vstack(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_trim(start = 1, end = 5) |>
  ffm_compile()

Vertically Stack Multiple Videos in an FFmpeg Pipeline

Description

Add a complex video filter that stacks several videos vertically (one above the other). It can also resize the videos to the same width.

Usage

ffm_vstack(object, shortest = FALSE, resize = FALSE)

Arguments

object

An FFmpeg pipeline (ffm) object created by ffm_files().

shortest

A logical that says whether to trim the duration of all videos to that of the shortest video. The default is FALSE.

resize

A logical that says whether to resize the input videos to the same width. Resizing takes longer, and for now it works only with two inputs. It fits both inputs to the same aspect ratio, so it assumes the inputs share one.

Details

This is the vertical form of ffm_hstack. Both are pipeline functions for several inputs. They force the -filter_complex path and manage their own stream labels internally. The glossary in vignette("tidymedia") explains media terms such as stream.

Value

object with an added instruction to stack the videos vertically.

See Also

ffm_hstack() for horizontal stacking, and compare_videos(), the task function built on both.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), print.tidymedia_ffm()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Stack two inputs one above the other (pass more than one input to ffm_files())
ffm_files(c(video, video), "output.mp4") |>
  ffm_vstack() |>
  ffm_compile()

Run a raw FFmpeg command

Description

Send a raw argument string to the FFmpeg command-line program. This is a direct command. The function passes the string to FFmpeg unchanged, after the path of the FFmpeg program. So you are responsible for the quoting and the order of the options.

Usage

ffmpeg(command)

Arguments

command

A string containing the arguments to pass to FFmpeg.

Value

A character vector containing the text output by FFmpeg.

See Also

ffmpeg_codecs() and ffmpeg_encoders() ask FFmpeg what it supports. The ⁠ffm_*()⁠ pipeline functions, such as ffm_run(), are a safer way to build a command.

Other direct command functions: ffprobe(), mediainfo()

Examples


# A direct command: the function passes the string to FFmpeg unchanged
ffmpeg("-version")


Get a data frame of all installed codecs

Description

Ask FFmpeg for its list of installed codecs, and return the list as a data frame with information about each codec. The glossary in vignette("tidymedia") explains media terms such as codec and encoder.

Usage

ffmpeg_codecs(sort_by_type = TRUE)

Arguments

sort_by_type

A logical. TRUE sorts the tibble by type and then by name. FALSE sorts it by name only. (default = TRUE)

Value

A tibble with the following variables:

name

A character vector including the name/code of each codec

details

A character vector including details about each codec

type

A factor vector indicating whether each codec supports "Video", "Audio" or "Subtitles"

decoding

A logical vector indicating whether each codec supports decoding

encoding

A logical vector indicating whether each codec supports encoding

intraframe

A logical vector indicating whether each codec is an intra-frame-only codec

lossy

A logical vector indicating whether each codec supports lossy compression

lossless

A logical vector indicating whether each codec supports lossless compression

See Also

ffmpeg_encoders() for the encoder list, ffm_codec() to set a codec in a pipeline, and ffmpeg() for the direct command.

Other capability functions: ffmpeg_encoders(), hardware_encoder(), refresh_ffmpeg_capabilities()

Examples


head(ffmpeg_codecs())
ffmpeg_codecs(sort_by_type = FALSE)


Get a data frame of all installed encoders

Description

Ask FFmpeg for its list of installed encoders, and return the list as a data frame with information about each encoder. The glossary in vignette("tidymedia") explains media terms such as codec and encoder.

Usage

ffmpeg_encoders(sort_by_type = TRUE)

Arguments

sort_by_type

A logical. TRUE sorts the tibble by type and then by name. FALSE sorts it by name only. (default = TRUE)

Value

A tibble with the following variables:

name

A character vector including the name/code of each encoder

details

A character vector including details about each encoder

type

A factor vector indicating whether each encoder supports "Video", "Audio" or "Subtitles"

frame_mt

A logical vector indicating whether each encoder supports frame-level multithreading

slice_mt

A logical vector indicating whether each encoder supports slice-level multithreading

experimental

A logical vector indicating whether each encoder is experimental

horiz_band

A logical vector indicating whether each encoder supports draw_horiz_band

direct_render

A logical vector indicating whether each encoders supports direct rending method 1

See Also

ffmpeg_codecs() for the codec list, ffm_codec() to set a codec in a pipeline, and ffmpeg() for the direct command.

Other capability functions: ffmpeg_codecs(), hardware_encoder(), refresh_ffmpeg_capabilities()

Examples


head(ffmpeg_encoders())
ffmpeg_encoders(sort_by_type = FALSE)


Send a command to the FFprobe program

Description

ffprobe() runs the FFprobe program with the arguments in command and returns its output. FFprobe reads information about media files.

Usage

ffprobe(command)

Arguments

command

A string with the arguments to give FFprobe.

Details

ffprobe() is a direct command. The package passes command to FFprobe exactly as you wrote it, so you must add any quotes that it needs. To get tibbles instead, use probe_all() and the other ⁠probe_*()⁠ functions. These functions quote their arguments for you.

Value

A character vector with the text that FFprobe writes to standard output, one element for each line. Messages on standard error, such as FFprobe's banner and errors, are not returned. On macOS and Linux, a shell redirect such as ⁠2>&1⁠ in command returns them too.

See Also

probe_all() and the other ⁠probe_*()⁠ functions, which return tibbles.

Other direct command functions: ffmpeg(), mediainfo()

Examples


ffprobe("-version")


Find the location of a dependency program

Description

Each of these functions returns the location of one program as a string: find_ffmpeg(), find_ffprobe(), find_ffplay() and find_mediainfo().

Usage

find_ffmpeg()

find_mediainfo()

find_ffprobe()

find_ffplay()

Details

The function looks on the PATH first. If the program is not there, the function reads the location that set_program() saved. That location is in a file under tools::R_user_dir("tidymedia", "config"). If neither place has the program, the function gives a warning and returns NULL.

Value

The location of the program as a string, or NULL when it could not be found.

Problems with a saved location

A saved location that no longer works gives a warning, and the function returns NULL. The warning has one of two classes that you can catch:

A line that holds only spaces counts as a location. So it gives tidymedia_location_gone, not tidymedia_location_unreadable.

To fix either problem, forget the location with unset_program(), or replace it with set_program().

Locations saved by earlier versions

Versions of the package before 0.2.0 saved locations in a different folder, rappdirs::user_config_dir("tidymedia", "R"). The functions still read a file in that folder. They read it only when the current folder has no file for the program. program_status() looks in the same places, in the same order.

A tidymedia_location_unreadable warning names the file that the function read. That file can be the one in the old folder.

set_program() writes to the current folder only. After it writes a file for a program, the old file for that program is not read.

unset_program() removes the file in both folders. So the old location does not come back after the current file is gone.

See Also

set_program() to save the location of a program that is not on the PATH, and install_on_win() to download FFmpeg on Windows.

Other program management functions: install_on_win(), program_status(), set_program(), unset_program()

Examples


# Returns the path to the binary, or NULL with a warning if it is not found
find_ffmpeg()
find_mediainfo()


Re-encode a video for web playback

Description

Re-encode a video into a widely compatible, web-friendly form: H.264 video with yuv420p and +faststart, and AAC audio. Odd dimensions are padded down to even values, as the codec requires. The glossary in vignette("tidymedia") explains media terms such as codec, pixel format and re-encode.

Usage

format_for_web(
  infile,
  outfile,
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a video file.

outfile

A string containing the path of the video file to write.

hardware

The encoder backend. "none" (default) uses software libx264. "nvenc" uses NVIDIA GPU H.264 encoding ("h264_nvenc"), and "videotoolbox" uses Apple GPU H.264 encoding ("h264_videotoolbox"). The backend you name is the one used. An unavailable one aborts unless fallback = TRUE. See has_hardware_encoder. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE re-encodes with software libx264 and a message. FALSE (default) aborts instead. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default) to leave the encoder's own default in place. It is the encoder's own rate-control value, passed through unchanged. libx264 reads it as -crf (0 to 51). h264_nvenc reads it as -cq (0 to 51), and h264_videotoolbox as -q:v (1 to 100). Each scale is its own: the same number means something different on each encoder. A value outside the encoder's range is refused. The encoder is libx264, h264_nvenc or h264_videotoolbox, as hardware chooses. When fallback = TRUE falls back to software, the value is dropped and the message says so, because it belonged to the hardware encoder's scale.

audio_stream

The audio track to carry into the output, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. The every-track family reads NULL this way: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_codec() and ffm_pixel_format(), among the pipeline functions it wraps; has_hardware_encoder() for the hardware toggle; standardize_video() for a configurable re-encode; format_for_web_batch() for the many-file form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
format_for_web(video, "web.mp4", run = FALSE)

Re-encode Many Videos for the Web From a Jobs Table

Description

Re-encode many videos into a widely compatible, web-friendly form, using one jobs table. This is the batch form of format_for_web(), for when you have more than one file. Each row is one input. The function is a thin wrapper over ffm_batch. It builds one reproducible command for each input. Each command uses the same fixed H.264, AAC and +faststart steps as format_for_web(), with no per-row settings. The glossary in vignette("tidymedia") explains media terms such as codec and re-encode.

Usage

format_for_web_batch(
  jobs,
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input. It needs at least an input column, the source path. An optional output column names the destination. Without it, each row's output name adds _web to the input's base name, with an .mp4 extension. The web re-encode always writes H.264 in mp4. For example, clip.mkv becomes clip_web.mp4. Two rows with the same destination path are refused before any row runs. That happens with a repeated output, or with two derived names that match. For example, clip.mov and clip.mkv both give clip_web.mp4. An optional numeric audio_stream column overrides the audio_stream argument for each row. NA keeps every audio track in that row. A numeric quality column overrides the quality argument per row (see quality). Any other columns are ignored, video_codec and audio_codec included. The sibling batch functions read those two columns as per-row overrides, but this one does not. The web recipe fixes which codecs the output uses: H.264 video and AAC audio. For per-row codecs, use a function that has them, such as standardize_video_batch or crop_video_batch.

hardware

The encoder backend for every row. "none" (default) uses software libx264. "nvenc" uses NVIDIA GPU H.264 encoding, and "videotoolbox" uses Apple GPU H.264 encoding. It applies to the whole batch and is not read as a column. See has_hardware_encoder. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE re-encodes with software libx264 and a message. FALSE (default) aborts instead. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default), applied to each row unless jobs carries a numeric quality column. In that column, NA leaves that row's encoder default in place, whatever the argument says. The value is the encoder's own rate-control value, passed through unchanged. Each cell is checked against the encoder its own row resolves to. A wrong cell is refused before any row runs, and the error names this function and the row. See format_for_web() for the encoders, their flags and ranges, and the values it refuses.

audio_stream

The audio track to carry into each output, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The every-track family reads NULL as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical: process the jobs in parallel with furrr (TRUE) or one at a time (FALSE, default). See ffm_batch for the future plan requirement.

...

Additional arguments forwarded to ffm_batch (e.g. verify, manifest, progress).

Value

The jobs tibble with an added command column. When run = TRUE, it also has a success column, plus verified or a provenance manifest, each when requested through .... See ffm_batch.

See Also

format_for_web(), the single-input form it wraps; ffm_batch(), the batch runner; standardize_video_batch() for a configurable re-encode.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(input = c(video, video), output = c("a.mp4", "b.mp4"))
format_for_web_batch(jobs, run = FALSE)

Get the duration of a media file

Description

get_duration() uses the MediaInfo program to look up the duration of a media file. You choose the section of the file and the unit.

Usage

get_duration(
  file,
  section = c("General", "Video", "Audio"),
  unit = c("ms", "sec", "min", "hour")
)

Arguments

file

A character vector of one or more media file paths.

section

A string indicating the MediaInfo section from which to query the duration value. Can be either "General", "Video", or "Audio" (default = "General").

unit

A string indicating whether the duration should be returned in milliseconds ("ms"), seconds ("sec"), minutes ("min"), or hours ("hour") (default = "ms").

Details

The function returns one number for each file. The ⁠probe_*()⁠ functions, mediainfo_query() and mediainfo_template() return tibbles instead.

Value

A double vector (one per file) giving the duration of the specified section in the specified units.

See Also

mediainfo_parameter() for arbitrary MediaInfo fields, and probe_all() to read information with FFprobe.

Other metadata functions: get_frame_rate(), get_height(), get_sample_rate(), get_width(), mediainfo_parameter(), mediainfo_query(), mediainfo_template(), probe_all(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
get_duration(video, unit = "sec")


Get the video frame rate of a media file

Description

get_frame_rate() uses the MediaInfo program to look up the video frame rate of a media file, in frames per second (fps). The glossary in vignette("tidymedia") explains media terms such as frame rate.

Usage

get_frame_rate(file)

Arguments

file

A character vector of one or more media file paths.

Details

The function returns one number for each file. The ⁠probe_*()⁠ functions, mediainfo_query() and mediainfo_template() return tibbles instead.

Value

A double vector (one per file) giving the video frame rate in fps.

See Also

mediainfo_parameter() for arbitrary MediaInfo fields, and probe_all() to read information with FFprobe.

Other metadata functions: get_duration(), get_height(), get_sample_rate(), get_width(), mediainfo_parameter(), mediainfo_query(), mediainfo_template(), probe_all(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
get_frame_rate(video)


Get the video height of a media file

Description

get_height() uses the MediaInfo program to look up the video height of a media file, in pixels (px).

Usage

get_height(file)

Arguments

file

A character vector of one or more media file paths.

Details

The function returns one number for each file. The ⁠probe_*()⁠ functions, mediainfo_query() and mediainfo_template() return tibbles instead.

Value

A double vector (one per file) giving the video height in px.

See Also

mediainfo_parameter() for arbitrary MediaInfo fields, and probe_all() to read information with FFprobe.

Other metadata functions: get_duration(), get_frame_rate(), get_sample_rate(), get_width(), mediainfo_parameter(), mediainfo_query(), mediainfo_template(), probe_all(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
get_height(video)


Get the audio sample rate of a media file

Description

get_sample_rate() uses the MediaInfo program to look up the audio sample rate of a media file, in hertz (Hz). The glossary in vignette("tidymedia") explains media terms such as sample rate.

Usage

get_sample_rate(file)

Arguments

file

A character vector of one or more media file paths.

Details

The function returns one number for each file. The ⁠probe_*()⁠ functions, mediainfo_query() and mediainfo_template() return tibbles instead.

Value

A double vector (one per file) giving the audio sample rate in Hz.

See Also

mediainfo_parameter() for arbitrary MediaInfo fields, and probe_all() to read information with FFprobe.

Other metadata functions: get_duration(), get_frame_rate(), get_height(), get_width(), mediainfo_parameter(), mediainfo_query(), mediainfo_template(), probe_all(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
get_sample_rate(video)


Get the video width of a media file

Description

get_width() uses the MediaInfo program to look up the video width of a media file, in pixels (px).

Usage

get_width(file)

Arguments

file

A character vector of one or more media file paths.

Details

The function returns one number for each file. The ⁠probe_*()⁠ functions, mediainfo_query() and mediainfo_template() return tibbles instead.

Value

A double vector (one per file) giving the video width in px.

See Also

mediainfo_parameter() for arbitrary MediaInfo fields, and probe_all() to read information with FFprobe.

Other metadata functions: get_duration(), get_frame_rate(), get_height(), get_sample_rate(), mediainfo_parameter(), mediainfo_query(), mediainfo_template(), probe_all(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
get_width(video)


Hardware video encoders

Description

These functions help with optional hardware video encoding. hardware_encoder() gives the hardware encoder name for a codec family. has_hardware_encoder() reports whether that encoder is available in the local FFmpeg build. The package supports two backends: NVIDIA nvenc (H.264, HEVC and AV1) and Apple videotoolbox (H.264 and HEVC). So hardware_encoder("h264", "nvenc") is "h264_nvenc", and hardware_encoder("h264", "videotoolbox") is "h264_videotoolbox". The glossary in vignette("tidymedia") explains media terms such as codec, container and hardware encoder.

Usage

hardware_encoder(codec = c("h264", "hevc", "av1", "prores"), hardware)

has_hardware_encoder(codec = c("h264", "hevc", "av1", "prores"), hardware)

Arguments

codec

The video codec family: one of "h264", "hevc", "av1", or "prores". These are the families the package recognizes, not the families a given backend covers. If the chosen hardware backend has no encoder for a family, the function refuses the call. The error names both the backend and the family (e.g. "av1" under "videotoolbox"). Both backends refuse "prores" today.

hardware

The backend: "nvenc" or "videotoolbox". Required, with no default. This set is narrower than the hardware argument of the task functions. There, "none" means "use no backend". That has no meaning here, so the function refuses it.

Details

has_hardware_encoder() is a cheap check. It asks whether FFmpeg lists the encoder (via ffmpeg_encoders). That list reflects how FFmpeg was built. It does not reflect whether working hardware and a driver are present at run time. An encode can still fail at run time on a machine with no capable GPU. To override detection in a known environment (or in tests), set options(tidymedia.hardware_encoders = ) to a character vector of encoder names to treat as available.

The hardware argument of the task functions uses the same encoder names and the same check. These task functions have that argument: standardize_video, format_for_web, anonymize_video, crop_video, segment_video, compare_videos, picture_in_picture, and separate_audio_video (and their _batch forms). Some of these functions have a video_codec that defaults to NULL (no codec named), and they assume the H.264 family. So a container that does not take H.264 (e.g. .webm) needs an explicit HEVC- or AV1-family video_codec. AV1 works only under "nvenc". Hardware decoding (-hwaccel) and GPU filter pipelines are out of scope. Use the ffmpeg direct command for those.

Value

hardware_encoder() returns a single encoder-name string (e.g. "h264_nvenc"). has_hardware_encoder() returns a length-one logical. Neither returns for a codec that the chosen hardware backend has no encoder for. That pair is a wrong argument, not a machine without something. So both give the error that codec describes above. has_hardware_encoder() returns FALSE only for a pair that the chosen backend has an encoder for and this FFmpeg build does not list.

See Also

ffmpeg_encoders for the full encoder list. These task functions have the hardware argument: standardize_video, format_for_web, anonymize_video, crop_video, segment_video, compare_videos, picture_in_picture, and separate_audio_video.

Other capability functions: ffmpeg_codecs(), ffmpeg_encoders(), refresh_ffmpeg_capabilities()

Examples


hardware_encoder("h264", "nvenc")
has_hardware_encoder("h264", "nvenc")


Install FFmpeg on Windows

Description

install_on_win() downloads a Windows build of FFmpeg and unpacks it. Then it saves the locations of ffmpeg, ffprobe and ffplay, as set_program() does. After that, the package can find these programs.

By default, the call downloads the latest "essentials" build from gyan.dev. It unpacks the build into the ffmpeg folder under tools::R_user_dir("tidymedia", "data").

By default, the call asks you to confirm before it does anything. The question names each file it will download and the folder it will unpack into. It also names the saved program locations that the install can replace. If you say no, the call returns FALSE and changes nothing.

This function works on Windows only. On any other system, it gives an error before it asks, writes or downloads anything. The error names the system it found. On macOS, you can install FFmpeg with ⁠brew install ffmpeg⁠. On Linux, you can use ⁠sudo apt-get install ffmpeg⁠. On any system, set_program() tells the package where an installed FFmpeg is.

Usage

install_on_win(
  download_url = NULL,
  install_dir = NULL,
  confirm = TRUE,
  archive_checksum = NULL
)

Arguments

download_url

A string with the address of the FFmpeg archive. If NULL, the call uses the latest "essentials" build from gyan.dev, a ⁠.7z⁠ archive.

install_dir

A string with the folder to install FFmpeg into. If NULL, the call uses the ffmpeg folder under tools::R_user_dir("tidymedia", "data"). CRAN allows packages to keep user data in that place.

confirm

TRUE or FALSE. Whether to ask before the call downloads or installs anything. Defaults to TRUE. In a session where no one can answer, TRUE gives an error that names the same items as the question. Pass confirm = FALSE to install without the question.

archive_checksum

A string with the expected SHA-256 checksum of the archive, as 64 hexadecimal characters in upper or lower case. Defaults to NULL. If you give a checksum, the call uses it for any source and downloads no checksum. If it is NULL and download_url is not the default source, the call checks nothing and says so.

Details

Before the call unpacks the archive, it checks the archive against a SHA-256 checksum. A checksum is a fingerprint of the file's contents. For the default source, the call downloads the checksum that gyan.dev publishes next to each build. That file has the archive's address with .sha256 added. For any other source, give the checksum in archive_checksum.

The published checksum comes from the same site as the archive, over the same connection. So the check finds a damaged or incomplete download. It does not find a source that someone has tampered with.

After the unpack, the call checks each program before it saves any location. The path must be one that R finds as a program. It must be a file, not a folder, and the file must not be empty. The call does not run the program. So a build for the wrong type of processor can pass this check.

The package needs ffmpeg and ffprobe. If either one fails the check, the call saves no location and gives an error. The error names each failed program and its full path. If ffplay is missing or fails the check, the install finishes. A message says that the call did not save ffplay.

Value

TRUE when the install finished. FALSE when you said no to the question, or when the call could not create the install folder. Other failures give an error. The section "Errors" lists the error classes the call gives. A wrong argument gives an error before any of these.

What a failed install leaves behind

When the call gives an error, it tries to leave the install folder as it found it. It removes the files that a failed unpack wrote. It removes a folder that the call created. It does not touch the files that were already in the folder, with one exception.

The exception is a file of yours that the failed unpack wrote over. The call removes that file too, because the file no longer holds what you put there.

On Windows, the removal can fail. After a failed unpack, the unpack library can still hold a file open. Windows does not delete a file that is open.

The error names by full path the entries of the first case below that applies:

Two errors come after a successful unpack: tidymedia_program_not_extracted and tidymedia_program_unusable. These errors leave the unpacked files in the folder, and they say so.

The call learns which files the unpack made from the archive's own list and from the folder. A program that the list names but that is not in the folder counts as not unpacked. For example, antivirus software can remove a program right after the unpack. The error then says that the unpack reported writing that file.

If none of the unpacked files are in the folder, tidymedia_program_not_extracted follows the usual rule. The call removes a folder that it created, and the error says so.

Errors

The call gives an error of its own class in these cases:

See Also

set_program() to save the location of a program you already have, and find_ffmpeg() to check where the package finds a program.

Other program management functions: find_ffmpeg(), program_status(), set_program(), unset_program()

Examples

## Not run: 
# Download and install a static FFmpeg build (Windows)
install_on_win()

## End(Not run)

Set a time limit for the rest of a function

Description

local_timeout() sets a time limit for the rest of the function that calls it. The limit applies to each FFmpeg, FFprobe or MediaInfo program that the function starts after this call. When the function returns, or stops with an error, the caller's own limit is back, except in the cases in Details.

Use with_timeout() to set a limit on one expression. Use local_timeout() to set a limit on the rest of a function, or on several calls that are hard to wrap in one expression.

Usage

local_timeout(seconds, .local_envir = parent.frame())

Arguments

seconds

A whole number of seconds. 0 means no limit, so local_timeout(0) removes a session limit for the rest of the function. A fraction, a negative number, a string or NULL gives an error, and the limit does not change.

.local_envir

The environment that holds the limit. The default is the function that calls local_timeout(). Change it only when you write a helper that sets a limit for its own caller. Inside a function, the environment must belong to a function that is still running. Suppose it belongs to a function that has returned, or it is an environment such as new.env(). Then the limit stays set with no error. withr::local_options() works the same way. At the top level of a script or the console, withr::defer() decides when the limit is undone.

Details

The limit applies to each program, not to the whole function. In a 100-row batch after local_timeout(600), each program that a row starts gets 600 seconds, plus the delay that with_timeout() describes. The workers of a parallel = TRUE run use the same limit.

R can wait up to 40 seconds past the limit, and with_timeout() explains why. It also explains what happens when a limit is reached.

Two calls in one function work like any two ⁠local_*()⁠ calls. The second limit applies until the function ends. Then both are undone, and the caller's limit is back.

In three cases, the caller's limit is not back when the function ends, and there is no error.

The first two cases also apply to withr::local_options(), because R's exit handlers work this way. They do not apply to withr::with_options(), which puts the option back itself.

Value

The caller's earlier setting, invisibly. It is a list with one element, the same form that withr::local_options() returns.

See Also

with_timeout() to set a limit for one expression. tidymedia-package describes the session options.

Examples

bounded <- function() {
  local_timeout(30)
  getOption("tidymedia.timeout")
}

# In force for the rest of that function...
bounded()

# ...and gone once it has returned.
getOption("tidymedia.timeout", default = "unset")

# Bound every program a whole function starts, at five minutes. Defining the
# function starts nothing; the limit applies when you call it.
convert_all <- function(files) {
  local_timeout(300)
  for (f in files) extract_audio(f, sub("[.][^.]*$", ".wav", f))
}


Run a MediaInfo command

Description

mediainfo() runs the MediaInfo program with the arguments in command and returns its output. MediaInfo reads information about media files.

Usage

mediainfo(command)

Arguments

command

A string with the arguments to give MediaInfo.

Details

mediainfo() is a direct command. The package passes command to MediaInfo exactly as you wrote it, so you must add any quotes that it needs. To get a tibble or a value instead, use mediainfo_template(), mediainfo_query() or mediainfo_parameter(). These functions quote their arguments for you.

Value

A character vector with the text that MediaInfo writes to standard output, one element for each line. Messages on standard error are not returned. On macOS and Linux, a shell redirect such as ⁠2>&1⁠ in command returns them too.

See Also

mediainfo_template(), mediainfo_query() and mediainfo_parameter() for a tibble or a value. get_duration() and the other ⁠get_*()⁠ functions for common single values.

Other direct command functions: ffmpeg(), ffprobe()

Examples


mediainfo("--Version")


Query a single parameter from a single MediaInfo section

Description

mediainfo_parameter() uses the MediaInfo program to read one value, such as the video width, from media files. MediaInfo groups its values in sections, such as "General", "Video" and "Audio". You name the section and the parameter to read.

Usage

mediainfo_parameter(file, section, parameter, typed = TRUE)

Arguments

file

A character vector of one or more media file paths.

section

A string. The name of the MediaInfo section to read parameter from.

parameter

A string. The name of the MediaInfo parameter to read from section.

typed

A logical. If TRUE (the default), the function converts the values to their natural type, for example to numbers. If FALSE, it returns strings.

Details

Give several files in file to get one value for each file. The function returns a vector, not a tibble. The ⁠probe_*()⁠ functions read similar information with FFprobe and return tibbles.

Value

A vector with one value for each element of file. A value is NA when MediaInfo prints more than one line, for example for a section it does not know. A parameter that section does not have gives an empty value. That value is NA when typed = TRUE and "" when typed = FALSE. A value is also NA for a file that does not exist or that reaches the time limit.

The function does not stop at those files. It reads the other files, and then gives one warning that names the files that do not exist or reached the limit. See with_timeout() for the time limit.

See Also

mediainfo_query() to read several parameters at once. mediainfo_template() to apply a whole template. probe_all() to read information with FFprobe. get_duration() and the other ⁠get_*()⁠ functions for common single values.

Other metadata functions: get_duration(), get_frame_rate(), get_height(), get_sample_rate(), get_width(), mediainfo_query(), mediainfo_template(), probe_all(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
mediainfo_parameter(video, section = "Video", parameter = "Width")


Query multiple parameters from a single MediaInfo section

Description

mediainfo_query() uses the MediaInfo program to read several parameters from one section, and returns a tibble. To read parameters from more than one section in one call, use mediainfo_template().

Usage

mediainfo_query(file, section, parameters, names = parameters, typed = TRUE)

Arguments

file

A character vector of one or more media file paths.

section

A string. The name of the MediaInfo section to read parameters from.

parameters

A character vector of one or more MediaInfo parameters to read from section.

names

A character vector of column names, one for each element of parameters. The default is parameters. The function keeps the names as you give them, but removes spaces at their start and end.

typed

A logical. If TRUE (the default), numeric columns become numbers and empty values become NA. If FALSE, all columns stay strings.

Details

Give several files in file to get one row for each file. The first column, file, names the input file. The ⁠probe_*()⁠ functions read similar information with FFprobe.

Value

A tibble with one row for each input file. The first column is file, and then there is one column for each parameter.

A file that the function could not read gets a row of NA values. The function reads the other files, and then gives one warning that names the files it could not read. A file that reaches the time limit counts as not read; see with_timeout().

See Also

mediainfo_parameter() to read a single value. mediainfo_template() to apply a whole template. probe_all() to read information with FFprobe. get_duration() and the other ⁠get_*()⁠ functions for common single values.

Other metadata functions: get_duration(), get_frame_rate(), get_height(), get_sample_rate(), get_width(), mediainfo_parameter(), mediainfo_template(), probe_all(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
mediainfo_query(video, section = "Video", parameters = c("Width", "Height"))


Describe media files by applying a MediaInfo template

Description

mediainfo_template() uses the MediaInfo program to describe media files, and returns a tibble. It applies a MediaInfo template, which can read many parameters from many sections.

Usage

mediainfo_template(
  file,
  template = c("brief", "extended", "custom"),
  templatefile = NULL,
  typed = TRUE
)

Arguments

file

A character vector of one or more media file paths.

template

A string. Use "brief" or "extended" for a template that comes with the package. Use "custom" to apply the file in templatefile.

templatefile

The path to your own MediaInfo template, a .txt file that makes MediaInfo print comma-separated values. Give it when template is "custom", and only then. The default is NULL.

typed

A logical. If TRUE (the default), numeric columns become numbers and empty values become NA. If FALSE, all columns stay strings.

Details

The package comes with two templates, "brief" and "extended". You can also give your own template file. Give several files in file to get one row for each file. The first column, file, names the input file. The ⁠probe_*()⁠ functions read similar information with FFprobe.

Value

A tibble with one row for each input file. The template sets the columns, their names and their order. The function keeps the column names of a custom template, but removes spaces at their start and end.

A file that the function could not read gets a row of NA values. The function reads the other files, and then gives one warning that names the files it could not read. A file that reaches the time limit counts as not read; see with_timeout().

See Also

mediainfo_query() to read one section. mediainfo_parameter() to read a single value. probe_all() to read information with FFprobe. get_duration() and the other ⁠get_*()⁠ functions for common single values.

Other metadata functions: get_duration(), get_frame_rate(), get_height(), get_sample_rate(), get_width(), mediainfo_parameter(), mediainfo_query(), probe_all(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
mediainfo_template(video, template = "brief")


Normalize a file's audio loudness (EBU R128)

Description

Normalize the perceived loudness of a file's audio toward an EBU R128 target. The function uses FFmpeg's single-pass loudnorm filter. It can also downmix the channel count and resample. The output holds one audio stream and no video, whatever the input and whatever container outfile names. So the output of this function is audio, as with extract_audio and convert_audio. It does not carry the other streams through. To normalize a recording's soundtrack and keep its picture, first normalize to an audio file. Then put the audio back with the picture using the ffmpeg direct command. The glossary in vignette("tidymedia") explains media terms such as LUFS, true peak and sample rate.

Usage

normalize_audio(
  infile,
  outfile,
  target_loudness = -23,
  true_peak = -1,
  loudness_range = 7,
  channels = NULL,
  sample_rate = NULL,
  audio_codec = NULL,
  two_pass = FALSE,
  audio_stream = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a media file (with audio). An input with no audio stream is an FFmpeg error, not a silent copy of the video.

outfile

A string containing the path of the audio file to write. The function accepts any container that FFmpeg can write. The compiled command does not depend on which container it is. An audio container (.wav, .flac) holds the result exactly as a video container (.mkv) does. The video container carries one audio stream and nothing else.

target_loudness

The target integrated loudness, in LUFS (a number in -70..-5; default -23, the EBU R128 target).

true_peak

The maximum true peak, in dBTP (a number in -9..0; default -1, the EBU R128 ceiling).

loudness_range

The target loudness range, in LU (a number in 1..50; default 7).

channels

The output channel count, e.g. 1 to downmix to mono (a positive whole number), or NULL (default) to keep the source layout.

sample_rate

The output sample rate in Hz, e.g. 48000 (a positive whole number). NULL (default) lets loudnorm choose. It resamples, up to 192 kHz and capped by the encoder, and does not keep the source rate. Set this argument to fix the output rate.

audio_codec

An optional string naming the output audio encoder (e.g. "aac", "libmp3lame", "flac"), passed to FFmpeg's -codec:a. NULL (default) sets no -codec:a, which leaves the default encoder of the output container in place. "copy" is an error. Loudness normalization filters the audio, so the stream must be re-encoded and cannot be copied.

two_pass

A logical. When TRUE, the function uses accurate two-pass (measured/linear) normalization. The default (FALSE) is single-pass. A first analysis pass measures the loudness of the input. A second correction pass feeds those measurements back with linear=true, so the output hits the EBU R128 target precisely. So two-pass always runs the analysis pass through FFmpeg, even when run = FALSE. It needs the binary and a readable input. Under run = FALSE, the analysis still runs. The returned value is the exact correction command, which is not run. The single-pass default touches no binary under run = FALSE. If the input is silent, the analysis pass measures its loudness as -inf. Normalizing silence to a target is undefined, so two-pass aborts with a clear error. The single-pass default leaves silence untouched. The batch form differs here. normalize_audio_batch does not abort on a silent row. It sets that row aside, marks it in a silent column, and normalizes the rest. When the analysis pass gives no usable measurement at all, the abort has class tidymedia_loudnorm_no_measurement. The batch form raises the same class, so one handler covers both. Where FFmpeg exited non-zero, the abort also carries tidymedia_ffmpeg_exit, and the exit number on tm_status. Where FFmpeg exited zero but printed no measurement block that can be parsed, the abort carries the shared class alone. The silence abort above is neither: a silent input was measured.

audio_stream

The audio track to normalize, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) normalizes the first audio track. The first-track family reads NULL this way: extract_audio, convert_audio and normalize_audio, and their _batch forms. The every-track family reads it as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. This function reads NULL as the first track only. The two-pass analysis measures each audio track, but the correction uses one set of measurements. Normalizing several tracks at once would apply one track's measurements to all of them. Under two_pass = TRUE, the analysis pass measures this same track. Only the named track reaches the output, and no video does, whatever the container. So an output name with a video extension gives a video file that holds only audio. An input with no audio at all is an FFmpeg error. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run the (correction) command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE). Under two_pass = TRUE this gates only the correction pass; the analysis pass runs regardless (see two_pass).

Details

The default targets follow EBU Recommendation R 128 (2014). They are target_loudness = -23 LUFS and true_peak = -1 dBTP. Loudness is measured per ITU-R BS.1770-4. The default loudness_range is 7. This is single-pass (dynamic) loudnorm. The same input and arguments always compile to one reproducible command, with no separate measurement pass. The filter changes the audio, so FFmpeg re-encodes it. Set audio_codec to name the output encoder, or leave it NULL to use the default of the output container. Leaving channels at NULL keeps the source channel layout. FFmpeg's loudnorm filter resamples its output, up to 192 kHz, capped by the encoder. So the output sample rate is not the source rate unless you set it. Set sample_rate to control the output rate.

The function warns when no audio_stream is named and infile carries tracks that the output will not. extract_audio and convert_audio emit the same warning. Naming a track with audio_stream silences it, as does suppressWarnings(classes = "tidymedia_dropped_audio"). The check costs one FFprobe call per distinct input, which is one call here, because this function takes a single infile. The warning is given when FFprobe is available and the input can be probed. Otherwise the check is skipped silently. It never runs under run = FALSE, and never changes the compiled command. Under two_pass = TRUE, the warning comes before the analysis pass. So it arrives while adding audio_stream can still save that pass.

To switch the check off and skip its FFprobe call, use options(tidymedia.check_tracks = FALSE) for the session. Use withr::local_options(tidymedia.check_tracks = FALSE) for the rest of one function.

Value

The compiled FFmpeg command (invisibly when run = TRUE). Under two_pass = TRUE this is the correction command built from the measured values.

References

EBU Recommendation R 128 (2014), Loudness normalisation and permitted maximum level of audio signals; ITU-R BS.1770-4.

See Also

ffm_loudnorm(), the pipeline function it wraps. normalize_audio_batch() for the many-file form. extract_audio() and convert_audio(), the other task functions whose output is one audio stream.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# The output holds audio only, so name an audio file for it
normalize_audio(video, "normalized.wav", run = FALSE)
# Normalize to a streaming target and downmix to mono
normalize_audio(video, "mono.wav", target_loudness = -16, channels = 1,
                run = FALSE)
# Name the output audio encoder instead of taking the container's default
normalize_audio(video, "normalized.m4a", audio_codec = "aac", run = FALSE)

Normalize Many Files' Audio Loudness From a Jobs Table

Description

Normalize the audio loudness of many input files (EBU R128) from a single jobs tibble. This is the batch (table-driven) form of normalize_audio(), for when you have more than one file to normalize. Each row is one input, and the only required column names its source. The function is a thin wrapper over ffm_batch. It gives one reproducible compiled command per input. Each row uses the same loudnorm pipeline, and the same check of each value, as normalize_audio(). Set two_pass = TRUE for accurate measured/linear normalization across the whole table (see two_pass). The glossary in vignette("tidymedia") explains media terms such as LUFS, encoder and sample rate.

Usage

normalize_audio_batch(
  jobs,
  target_loudness = -23,
  true_peak = -1,
  loudness_range = 7,
  channels = NULL,
  sample_rate = NULL,
  audio_codec = NULL,
  two_pass = FALSE,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input and (at least) an input column (source path). An optional output column names the destination. Without it, the function derives one per row. It appends _normalized to the basename of each input and keeps the extension of the input (e.g. clip.mkv becomes clip_normalized.mkv). The derived name keeps a video extension while the file itself holds audio only. So name an output column yourself when that matters. The function refuses two rows that name the same output path before any row runs. With two_pass = TRUE, that is before the analysis pass. The refusal covers a path repeated in the output column, or a repeated input when there is no output column. Five loudness arguments can also appear as a column that overrides the argument per row. They are target_loudness, true_peak, loudness_range, channels and sample_rate. Rows that omit the column fall back to the value of the argument. An optional audio_codec column (character) names the output audio encoder of each row. There, NA means "leave the encoder unset". Rows that omit it fall back to the audio_codec argument. An optional numeric audio_stream column likewise overrides the audio_stream argument per row. There, NA normalizes the first audio track of that row. Any other columns are ignored.

target_loudness, true_peak, loudness_range

The EBU R128 loudness targets applied to every row, unless jobs carries a column of the same name (see jobs). Defaults follow EBU Recommendation R 128 (2014): target_loudness = -23 LUFS, true_peak = -1 dBTP, loudness_range = 7 LU.

channels

The output channel count applied to every row, unless jobs carries a channels column, e.g. 1 to downmix to mono. NULL (default) keeps each source's channel layout.

sample_rate

The output sample rate in Hz applied to every row, unless jobs carries a sample_rate column. NULL (default) lets loudnorm choose. It resamples, up to 192 kHz and capped by the encoder, and does not keep the source rate. Set this argument to fix the output rate.

audio_codec

The output audio encoder applied to every row, unless jobs carries an audio_codec column, e.g. "aac". NULL (default) sets no -codec:a, which leaves the default encoder of the output container in place. "copy" is an error. Loudness normalization filters the audio, so it must be re-encoded. See normalize_audio.

two_pass

A logical that selects the normalization mode for every row. It applies to the whole table and is not a per-row column. FALSE (default) keeps the single-pass loudnorm pipeline. TRUE runs accurate two-pass (measured/linear) normalization in two phases. An analysis pass first measures the loudness of every input. It honors parallel and the targets of each row. A correction pass then feeds those measurements back with linear=true, so each output hits its EBU R128 target precisely. This is the table-wide form of two_pass in normalize_audio. The result shows the five measured values as columns measured_I, measured_TP, measured_LRA, measured_thresh and offset. Two-pass must measure each input. So it always runs the analysis pass through FFmpeg, even when run = FALSE. It needs the binary and readable inputs. If the analysis of any row fails or gives no measurement that can be parsed, the call aborts and names those rows. It aborts before it builds any correction command. That abort has class tidymedia_loudnorm_no_measurement, the same class that normalize_audio raises for this event. It carries the same row numbers on tm_rows, alongside tm_row_status. That field has the FFmpeg exit status of each row, or NA where the row exited zero but printed nothing that can be parsed. It carries no single exit status on tm_status, and it does not have class tidymedia_ffmpeg_exit. The reason is that it also fires for rows that exited zero. A batch can mix causes, so there is no one number to report. The one-file form carries both only where FFmpeg exited non-zero. Where FFmpeg exited zero and printed nothing that can be parsed, the one-file abort carries the shared class alone, with no tm_status either. Silent rows are the exception. A silent input (analysis loudness -inf) cannot be normalized to a target, but one silent row does not abort the batch. The function normalizes the rows that are not silent. It marks the silent rows in a logical silent column, with success = FALSE and no output written, and a warning names them. This is where the batch form and the one-file form differ. normalize_audio aborts on a silent input, because one silent input is the whole call. Here, the other rows still have work to do. The single-pass default touches no binary under run = FALSE.

audio_stream

The audio track to normalize, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) normalizes the first audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The first-track family reads NULL as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The every-track family reads it as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. This function reads NULL as the first track only. The two-pass analysis measures each audio track, but the correction uses one set of measurements. Normalizing several tracks at once would apply one track's measurements to all of them. Under two_pass = TRUE, the analysis pass measures this same track. Only the named track reaches the output, and no video does, whatever the container. So an output name with a video extension gives a video file that holds only audio. An input with no audio at all is an FFmpeg error. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each input's command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE). Under two_pass = TRUE this gates only the correction pass; the analysis pass runs regardless (see two_pass).

parallel

A logical passed to ffm_batch: normalize in parallel with furrr (TRUE) or sequentially (FALSE, default). Parallelism follows the active future plan. TRUE under the default sequential plan runs one input at a time and warns. Set a plan first, e.g. future::plan(future::multisession).

...

Additional arguments forwarded to ffm_batch, such as verify, manifest, checksums, and progress.

Details

The function warns once for the whole batch when a row names no audio_stream and its input carries tracks that the output will not. The warning names every affected row. Naming a track silences it. Use the audio_stream argument, or an audio_stream cell on every row. suppressWarnings(classes = "tidymedia_dropped_audio") silences it too. The check costs one FFprobe call per distinct input it has to probe. A repeated input is probed once, and a row that names a track is not probed at all. The warning is given when FFprobe is available and the input can be probed. Otherwise the check is skipped silently. Those probes run one at a time, before any row starts, so parallel does not reach them. A sweep long enough to look like a hang reports its progress. The check never runs under run = FALSE and never changes any compiled command. It is skipped entirely when every row names a track. Under two_pass = TRUE, the warning comes before the analysis pass. So it arrives while adding audio_stream can still save that pass.

To switch the check off and skip the whole sweep, use options(tidymedia.check_tracks = FALSE) for the session. Use withr::local_options(tidymedia.check_tracks = FALSE) for the rest of one function.

Value

The tibble returned by ffm_batch: jobs with an added command column. When output was derived, it also has the resolved output column. When run = TRUE, it has a success column, plus any columns the forwarded arguments add, such as verified. Under two_pass = TRUE, the result also carries the five measured columns (measured_I etc.) and a logical silent column. The command column then holds the linear correction commands. It is NA for silent rows, which carry NA measurements and are not normalized. The columns of the two-pass result do not depend on how many rows are silent. The verified column (under verify) and the provenance manifest (under manifest, read with ffm_manifest) are present whenever requested. That holds even when every row is silent. Silent rows carry NA for those outputs.

References

EBU Recommendation R 128 (2014), Loudness normalisation and permitted maximum level of audio signals; ITU-R BS.1770-4.

See Also

normalize_audio() for the single-input form. ffm_batch() for the batch runner and the arguments forwarded through .... standardize_video_batch() for the table-driven form on the video side.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(
  input           = c(video, video),
  output          = c(tempfile(fileext = ".m4a"), tempfile(fileext = ".m4a")),
  target_loudness = c(-23, -16)
)
# run = FALSE compiles one command per input without calling FFmpeg
normalize_audio_batch(jobs, run = FALSE)

# Accurate two-pass (measured/linear) normalization across the whole table.
# This one runs FFmpeg to measure each input, so it needs the binary.
if (nzchar(Sys.which("ffmpeg"))) {
  normalize_audio_batch(jobs, two_pass = TRUE)
}


Inset one video over another (picture-in-picture)

Description

Composite a smaller overlay video onto a main video in one corner (or the center). This is the classic picture-in-picture layout for pairing a speaker with a screen recording, or a stimulus with a webcam. Built on the ffm_overlay pipeline function, which resizes the overlay to a fraction of the main video's width and positions it. The glossary in vignette("tidymedia") explains media terms such as codec, encoder and stream copy.

Usage

picture_in_picture(
  main,
  overlay,
  outfile,
  position = c("topright", "topleft", "bottomright", "bottomleft", "center"),
  scale = 0.25,
  margin = 16,
  audio_input = NULL,
  video_codec = NULL,
  audio_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  run = TRUE
)

Arguments

main

A string giving the path to the background (full-size) video.

overlay

A string giving the path to the inset video.

outfile

A string giving the path to write the result to.

position

Where to place the inset: one of "topright" (default), "topleft", "bottomright", "bottomleft", or "center".

scale

The inset's width as a fraction of the main video's width, aspect preserved (0 < scale <= 1). (default = 0.25)

margin

The gap in pixels between the inset and the video edges (ignored for position = "center"). (default = 16)

audio_input

The input file whose audio to keep, as a number that counts from 0. 0 is the first file you pass and 1 is the second. This counts the function's inputs, not the audio tracks of one input. So it is a different index from audio_stream on the functions that take one input. NULL (default) selects no audio at all, so the output is silent. This differs from audio_stream = NULL, which still selects audio. An input number the call does not have gives an R error, before FFmpeg runs. See audio_stream. (default = NULL)

video_codec

A string naming the output video codec, or NULL (default) to leave it unset. Then the output container's default encoder is used, and the compiled command is the same as one that never named a codec.

audio_codec

A string naming the codec for the carried audio track. "copy" (default) stream-copies it through untouched. Name an encoder, such as "aac", to transcode it. NULL leaves the codec unset, so the output container's default encoder is used. When audio_input is NULL, no audio reaches the output, so nothing is emitted. Naming an encoder in that case is an error.

hardware

The encoder backend. "none" (default) uses the software video_codec. "nvenc" uses NVIDIA GPU encoding (H.264, HEVC and AV1), and "videotoolbox" uses Apple GPU encoding (H.264 and HEVC). A backend uses its own encoder for the family of video_codec. For example, "libx264" becomes "h264_nvenc" or "h264_videotoolbox". With the default video_codec = NULL, the H.264 family is assumed. So a non-H.264 container, such as .webm, needs an explicit HEVC- or AV1-family video_codec (AV1 only under "nvenc"). See has_hardware_encoder for availability and its caveats. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE encodes in software with a message. FALSE (default) aborts instead. With video_codec = NULL, the fallback leaves the codec unset rather than picking one, so the codec never changes silently. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default) to leave the encoder's own default in place. It is the encoder's own rate-control value, passed through unchanged. libx264 and libx265 read it as -crf (0 to 51). The nvenc encoders read it as -cq (0 to 51), and the videotoolbox encoders as -q:v (1 to 100). Each scale is its own: the same number means something different on each encoder. A value outside the encoder's range is refused. An encoder outside those seven, such as libvpx-vp9, is refused with quality set. So is a video_codec of "copy", or of NULL under hardware = "none". When fallback = TRUE falls back to software, the value is dropped and the message says so, because it belonged to the hardware encoder's scale.

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Details

Audio is dropped unless audio_input names an input to carry (0 = the main video, 1 = the overlay). A carried track is stream-copied unless audio_codec names an encoder.

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_overlay(), the pipeline function it wraps; has_hardware_encoder() for the hardware argument; compare_videos() for side-by-side stacking.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
picture_in_picture(video, video, "pip.mp4", run = FALSE)

Inset One Video Over Another For Many Outputs From a Jobs Table

Description

Composite an inset (overlay) video onto a main video for many outputs from a single jobs tibble. This is the batch (table-driven) form of picture_in_picture(), for when you have more than one to produce. Its two inputs have distinct roles, so jobs carries fixed main and overlay columns (not a list-column) plus an output column. This is a thin wrapper over ffm_batch: one reproducible overlay command per row, sharing the pipeline with picture_in_picture(). The glossary in vignette("tidymedia") explains media terms such as codec, encoder and stream copy.

Usage

picture_in_picture_batch(
  jobs,
  position = c("topright", "topleft", "bottomright", "bottomleft", "center"),
  scale = 0.25,
  margin = 16,
  audio_input = NULL,
  video_codec = NULL,
  audio_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per output and (at least) main (background path), overlay (inset path), and output (destination path) columns. Optional position, scale, margin, audio_input, video_codec, and audio_codec columns override the like-named arguments per row (a row omitting one falls back to the argument). In an audio_input column, NA means "drop audio", the column's way of writing the scalar's NULL. In a video_codec or audio_codec column, it means "leave the codec unset". A numeric quality column overrides the quality argument per row (see quality). Two rows given the same output path are refused before any row runs; other columns are ignored.

position, scale, margin

Defaults applied to every row lacking the corresponding column. position is one of "topright" (the default), "topleft", "bottomright", "bottomleft" or "center"; a position column is held to those same five values, per row. See picture_in_picture() for their fuller meaning.

audio_input

The input file whose audio to keep, as a number that counts from 0. 0 is the first file you pass and 1 is the second. This counts the function's inputs, not the audio tracks of one input. So it is a different index from audio_stream on the functions that take one input. NULL (default) selects no audio at all, so the output is silent. This differs from audio_stream = NULL, which still selects audio. An input number the call does not have gives an R error, before FFmpeg runs. Without an audio_input column, the argument applies to every row. An NA cell in that column means NULL for that row, so that output has no audio. See audio_stream. (default = NULL)

video_codec

A string naming the output video codec, applied to every row lacking a video_codec column. NULL (default) leaves it unset, so each output keeps its container's default encoder.

audio_codec

A string naming the codec for the carried audio track, applied to every row lacking an audio_codec column. "copy" (default) stream-copies it. Name an encoder to re-encode it, or NULL to leave the codec unset. A row carrying no audio emits no -codec:a, and naming an encoder on such a row is an error.

hardware, fallback

The encoder backend and its fallback behavior, applied to the whole batch. They are a property of the machine, not of a row, so neither is read as a jobs column. See picture_in_picture(). Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows. A call can also contradict itself by naming an audio_codec with no audio carried into the output. Such a call is refused for the contradiction first, whether or not this machine has the encoder. A per-row value error likewise reports ahead of the encoder check. Examples are a negative margin, an audio_input index outside the two inputs, and a position outside the five accepted values. A value error and a contradiction resolve the same way whether the value arrived as an argument or in a jobs column. The contradiction reports first.

quality

A number, or NULL (default), applied to each row unless jobs carries a numeric quality column. In that column, NA leaves that row's encoder default in place, whatever the argument says. The value is the encoder's own rate-control value, passed through unchanged. Each cell is checked against the encoder its own row resolves to. A wrong cell is refused before any row runs, and the error names this function and the row. See picture_in_picture() for the encoders, their flags and ranges, and the values it refuses.

run

A logical: run each command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical: process the jobs in parallel with furrr (TRUE) or one at a time (FALSE, default). See ffm_batch for the future plan requirement.

...

Additional arguments forwarded to ffm_batch (e.g. verify, manifest, progress).

Value

The jobs tibble with an added command column. When run = TRUE, it also has a success column, plus verified or a provenance manifest, each when requested through .... See ffm_batch.

See Also

picture_in_picture(), the one-output function it wraps; ffm_batch(), the batch runner; has_hardware_encoder() for the hardware argument. concatenate_videos_batch() and compare_videos_batch(), the other batch functions that take several inputs per row.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(main = video, overlay = video, output = "pip.mp4")
picture_in_picture_batch(jobs, run = FALSE)

Print an FFmpeg pipeline

Description

Print a tidymedia ffm pipeline by showing the FFmpeg command it currently compiles to (via ffm_compile).

Usage

## S3 method for class 'tidymedia_ffm'
print(x, ...)

Arguments

x

A tidymedia ffm pipeline object created by ffm_files.

...

Ignored.

Value

x, invisibly.

See Also

ffm_compile(), which produces the printed command.

Other pipeline functions: ffm_batch(), ffm_codec(), ffm_compile(), ffm_concat(), ffm_copy(), ffm_crop(), ffm_drawbox(), ffm_drop(), ffm_files(), ffm_fps(), ffm_hstack(), ffm_jobs(), ffm_loudnorm(), ffm_map(), ffm_output_options(), ffm_overlay(), ffm_pixel_format(), ffm_run(), ffm_scale(), ffm_seek(), ffm_trim(), ffm_vstack()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
ffm_files(video, "output.mp4") |>
  ffm_trim(start = 1, end = 5)

Look up information about media files using FFprobe

Description

probe_all() uses the FFprobe program to read information about media files. It returns two tibbles. One describes each file as a whole, and one describes each stream in the files.

Usage

probe_all(infile, typed = TRUE, parallel = FALSE)

Arguments

infile

A character vector of one or more media files to probe, as file paths or web links.

typed

A logical. If TRUE (the default), numeric columns become integers or doubles, and FFprobe's "N/A" becomes NA. Fractions, ratios, hex identifiers and text stay as strings. If FALSE, every value stays a string.

parallel

A logical. If TRUE, the function probes the files in parallel with furrr. If FALSE (the default), it probes them one at a time. A parallel run uses the active future::plan(). It warns when that plan is sequential, because the run is then no faster. The output is the same either way, with the same rows in the same order. parallel = TRUE needs the furrr package, and only then does the function check for it.

Details

Give several files in infile to read them all in one call. The function stacks the rows, and the first column, file, names the input file. So you can join and filter the results for a whole batch with dplyr.

The MediaInfo functions, ⁠mediainfo_*()⁠, return tibbles or values. The ⁠get_*()⁠ functions return one value for each file.

The glossary in vignette("tidymedia") explains media terms such as container and stream.

Value

A list of two tibbles. container has one row for each input file. streams has one row for each stream. Both tibbles start with a file column that names the input file. A file with no readable streams gets one row in streams, with NA in every other column.

The function does not stop at a file that it could not probe. That file gets a row of NA values in both tibbles, and the function gives a warning. A file that reaches the time limit counts as not probed; see with_timeout().

See Also

mediainfo_template() and mediainfo_query() to read information with MediaInfo. get_duration() and the other ⁠get_*()⁠ functions for single values.

Other metadata functions: get_duration(), get_frame_rate(), get_height(), get_sample_rate(), get_width(), mediainfo_parameter(), mediainfo_query(), mediainfo_template(), probe_container()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
info <- probe_all(video)
info$container
info$streams


Shortcut functions for probing specific information

Description

These functions return one part of what probe_all() returns. probe_container() returns the container tibble, and probe_streams() returns the streams tibble. probe_video() and probe_audio() return only the video rows or the audio rows of streams.

Usage

probe_container(probe = NULL, infile = NULL, typed = TRUE, parallel = FALSE)

probe_streams(probe = NULL, infile = NULL, typed = TRUE, parallel = FALSE)

probe_video(probe = NULL, infile = NULL, typed = TRUE, parallel = FALSE)

probe_audio(probe = NULL, infile = NULL, typed = TRUE, parallel = FALSE)

Arguments

probe

A list made by probe_all(). Must be NULL if you give infile.

infile

A character vector of one or more media files. Must be NULL if you give probe.

typed

A logical that the function passes to probe_all() when you give infile. The default is TRUE. The function ignores it when you give probe.

parallel

A logical that the function passes to probe_all() when you give infile. If TRUE, it probes the files in parallel with furrr. If FALSE (the default), it probes them one at a time. The function ignores it when you give probe, because nothing is left to probe.

Details

Give each function either the output of probe_all() in probe, or one or more files in infile. Give exactly one of the two, or the function gives an error. With infile, the function probes the files again. For large files, probe once with probe_all() and reuse the result.

These functions use FFprobe and return tibbles. The MediaInfo functions, ⁠mediainfo_*()⁠, and the ⁠get_*()⁠ functions are the other ways to read information. The glossary in vignette("tidymedia") explains media terms such as container and stream.

Value

A tibble with only the requested information. When you give infile, a file that could not be probed gives a warning, as in probe_all().

See Also

probe_all() for the full probe. mediainfo_query() to read information with MediaInfo. get_width() and the other ⁠get_*()⁠ functions for single values.

Other metadata functions: get_duration(), get_frame_rate(), get_height(), get_sample_rate(), get_width(), mediainfo_parameter(), mediainfo_query(), mediainfo_template(), probe_all()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Probe directly from a file location ...
probe_container(infile = video)
# ... or reuse a probe object to avoid reprobing large files
info <- probe_all(video)
probe_video(info)
probe_audio(info)


Report which dependency programs tidymedia can find

Description

program_status() looks for the four programs that the package uses: ffmpeg, ffprobe, ffplay and mediainfo. It returns a table with one row for each program. The row shows where the program is and which version it reports. The call does not install, write or change anything.

Usage

program_status()

Details

The call looks in the same places as find_ffmpeg(). First it looks on the PATH, then at a location saved by set_program(). For locations saved by versions before 0.2.0, see the section "Locations saved by earlier versions" in find_ffmpeg().

A program that is not installed and has no saved location gets NA in both columns. This case gives no warning, so four missing programs give one table and not four warnings.

A saved location that cannot be used still gives a warning. Without it, the NA would look like a program you never had. Each warning names the saved location or the file that holds it, so you can fix it. There are two cases:

In both cases, the row has NA in both columns. unset_program() forgets the location, and set_program() replaces it.

The version is what the program reports about itself. For ffmpeg, ffprobe and ffplay, it is the FFmpeg build number. For mediainfo, it is the MediaInfo library version.

Sometimes the call finds a program but cannot get its version. Then the row has a location and an NA version. This happens when the program call fails. It also happens when the time limit in options(tidymedia.timeout = ) stops it.

Value

A tibble with one row for each program and three columns:

See Also

find_ffmpeg() and the other ⁠find_*()⁠ functions to look up one program. set_program() to save the location of a program that is not on the PATH. unset_program() to forget a saved location.

Other program management functions: find_ffmpeg(), install_on_win(), set_program(), unset_program()

Examples


# One row per program; NA where the program was not found
program_status()


Forget what tidymedia remembers about your FFmpeg build

Description

Discard the package's record of which encoders your FFmpeg build has. The next query then asks FFmpeg again.

Usage

refresh_ffmpeg_capabilities()

Details

The first call in an R session that uses hardware = "nvenc" or hardware = "videotoolbox" asks FFmpeg which encoders it has. The package remembers that answer for the rest of the session. Later calls reuse it and do not start FFmpeg again each time, so a large batch stays fast.

So the package does not see a change to your FFmpeg build until you discard the record. Examples of a change are a new FFmpeg install, a new graphics card (GPU) driver, or a different FFmpeg program. There are three ways to discard the record:

The glossary in vignette("tidymedia") explains media terms such as encoder and hardware encoder.

Value

NULL, invisibly. Called for its side effect.

Parallel workers

Each R process keeps its own record, and a worker does not get the record of your session. So in a batch on W workers, each worker asks FFmpeg once. Your session can also ask once, before the jobs start. Discarding the record in your session does not reach the workers.

The tidymedia.hardware_encoders option works in a different way. The package copies your value into each worker for the duration of the call, and then puts back the worker's own value. So a batch under your setting does not ask FFmpeg for an encoder list at all. Every worker gives the same answer as your session.

Functions that never use the record

ffmpeg_encoders and ffmpeg_codecs ask FFmpeg on every call. So they always show the build as it is now, whether or not you called this function.

See Also

has_hardware_encoder uses the remembered answer. hardware_encoder gives the encoder name without asking FFmpeg. ffmpeg_encoders always gives a fresh encoder list. set_program points the package at a different FFmpeg program.

Other capability functions: ffmpeg_codecs(), ffmpeg_encoders(), hardware_encoder()

Examples

# After installing FFmpeg, or a GPU driver or OS update mid-session:
refresh_ffmpeg_capabilities()

Sample frames from a video at a fixed rate

Description

Sample a video into a numbered image sequence. Sample at a fixed rate (fps) or at a fixed interval (interval, seconds between frames). This is the first step for per-frame coding and for computer-vision feature pipelines. Provide exactly one of fps or interval.

Usage

sample_frames(
  infile,
  outdir,
  fps = NULL,
  interval = NULL,
  format = "png",
  prefix = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a video file.

outdir

A string naming the directory to write the image sequence to. The function creates it (recursively) if it does not exist.

fps

The sampling rate, in frames per second: either a positive number or an FFmpeg framerate expression string (for example "30000/1001"). Provide exactly one of fps or interval.

interval

The number of seconds between sampled frames (a positive number). The function uses the reciprocal as the frame rate. Provide exactly one of fps or interval.

format

A string giving the output image file extension (one of "png", "jpg", "jpeg", "bmp", "tif", "tiff", "webp"). (default = "png")

prefix

A string used as the basename stem of each image, or NULL to derive it from infile's basename. (default = NULL)

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Details

extract_frame saves one frame, and extract_frame_batch saves a set of frames that you list. This function is different. It builds a single FFmpeg command whose output is a printf-style file name pattern. FFmpeg's image2 muxer fills the pattern. FFmpeg decides the frame count when it decodes the video, and you do not list the frames. The function writes frames to outdir as <prefix>_<n>.<format>, where <n> is a zero-padded integer starting at 1. The glossary in vignette("tidymedia") explains media terms such as frame rate.

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_fps(), the pipeline function it uses to set the sampling rate. extract_frame() for a single frame, and extract_frame_batch() for a set of frames that you list. sample_frames_batch() for the many-file form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# run = FALSE returns the reproducible command instead of executing it
sample_frames(video, tempdir(), fps = 2, run = FALSE)

Sample frames from many videos at a fixed rate from a jobs table

Description

Sample many videos into numbered image sequences, using one jobs table. This is the batch form of sample_frames(). Each row is one input video, sampled at a fixed rate into its own image sequence. The function is a thin wrapper over ffm_batch. It builds one reproducible command for each input. The glossary in vignette("tidymedia") explains media terms such as frame rate.

Usage

sample_frames_batch(
  jobs,
  fps = NULL,
  interval = NULL,
  outdir = NULL,
  format = "png",
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input. It needs at least an input column (source path). An optional outdir column gives the output directory for that row's sequence. When it is absent, the function derives one as <input-base>_frames beside each input. Optional fps and interval columns override the rate per row. The function ignores any other columns. The function refuses two rows whose image sequences would share a file-name pattern, before any row runs. Two rows share a pattern when they have the same output directory path and the same input file name without its extension. The directory path can come from the column, from the outdir argument, or from the derived name.

fps, interval

The sampling rate applied to every row, as in sample_frames(). A per-row column of the same name overrides it. Supply exactly one of the two (as an argument or a column). (default = NULL)

outdir

An optional single output directory for all rows. An outdir column overrides it. When both are absent, the function derives one directory per input. (default = NULL)

format

A string giving the output image file extension, as in sample_frames(). (default = "png")

run

A logical: run each input's command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical passed to ffm_batch: sample in parallel with furrr (TRUE) or one after another (FALSE, default). Parallel work follows the active future plan. TRUE under the default sequential plan runs one at a time and warns.

...

Additional arguments forwarded to ffm_batch, such as verify, manifest, checksums, and progress.

Details

Supply the sampling rate once as the single fps or interval argument, which applies to every row. Or supply it per row as an fps or interval column, which overrides the argument of the same name. Supply exactly one of the two, fps or interval, across arguments and columns.

Value

The tibble returned by ffm_batch: jobs with an added command column. When outdir was derived, it also has the resolved outdir column. When run = TRUE, it has a success column, plus any columns the forwarded arguments add, such as verified.

See Also

sample_frames() for the single-video form. ffm_batch() for the batch runner and the arguments passed on through .... extract_frame_batch() for the batch function that takes a list of frames.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(
  input  = c(video, video),
  outdir = c(file.path(tempdir(), "a"), file.path(tempdir(), "b"))
)
# run = FALSE compiles one command per input without calling FFmpeg
sample_frames_batch(jobs, fps = 2, run = FALSE)

Segment Video

Description

Use FFmpeg to quickly break a single video file into multiple smaller video files (with the same encoding). Pairs of start and stop timestamps set the segments. The function names each segment file after infile. It appends a suffix of an underscore (_) and an integer indicating which segment, based on the order provided in start and end. The glossary in vignette("tidymedia") explains media terms such as codec, keyframe and stream copy.

Usage

segment_video(
  infile,
  start,
  end,
  outfiles = NULL,
  reencode = TRUE,
  video_codec = NULL,
  audio_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE
)

Arguments

infile

A string containing the path to a video file.

start

A vector containing one or more timestamps indicating the start of each segment to create. Can be either a numeric vector indicating seconds or a character vector with time duration syntax. Must have the same length as end.

end

A vector containing one or more timestamps indicating the stop of each segment to create. Can be either a numeric vector indicating seconds or a character vector with time duration syntax. Must have the same length as start.

outfiles

Either NULL or a character vector indicating the filename (with extension) for each segment to create. If NULL, will append a zero-padded integer to infile. If not NULL, must have the same length as start, and each element must be a single string. So the function accepts a list of strings as well as a character vector. This function itself refuses a missing value or a number in any position, before the per-segment step below it can. Two segments given the same path are refused before any segment is cut.

reencode

A logical passed to ffm_seek: cut each segment frame-accurately by re-encoding (TRUE, default) or with a fast, lossless copy that snaps to keyframes (FALSE). See ffm_seek for the trade-off.

video_codec

A string naming the output video codec, or NULL (default) to leave it unset. Then the output container's default encoder is used, and the compiled command is the same as one that never named a codec. A stream copy runs no encoder, so naming a codec (or a hardware backend) alongside reencode = FALSE is an error.

audio_codec

A string naming the output audio codec. "copy" (default) stream-copies the audio through untouched. Name an encoder, such as "aac", to transcode it. NULL leaves the codec unset, so the output container's default encoder is used. A stream copy (reencode = FALSE) always copies the audio, so any other value is an error there. Stream-copying fails if the output container cannot hold the source audio codec (e.g. FLAC in .mp4). Name an encoder instead.

hardware

The encoder backend. "none" (default) uses the software video_codec. "nvenc" uses NVIDIA GPU encoding (H.264, HEVC and AV1), and "videotoolbox" uses Apple GPU encoding (H.264 and HEVC). A backend uses its own encoder for the family of video_codec. For example, "libx264" becomes "h264_nvenc" or "h264_videotoolbox". With the default video_codec = NULL, the H.264 family is assumed. So a non-H.264 container, such as .webm, needs an explicit HEVC- or AV1-family video_codec (AV1 only under "nvenc"). See has_hardware_encoder for availability and its caveats. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows. A call can also contradict itself by asking for GPU encoding on a cut that stream-copies. Such a call is refused for the contradiction first, whether or not this machine has the encoder. The stream-copy conflict named under reencode is caught first, so such a call aborts without probing.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE encodes in software with a message. FALSE (default) aborts instead. With video_codec = NULL, the fallback leaves the codec unset rather than picking one, so the codec never changes silently. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default) to leave the encoder's own default in place. It is the encoder's own rate-control value, passed through unchanged. libx264 and libx265 read it as -crf (0 to 51). The nvenc encoders read it as -cq (0 to 51), and the videotoolbox encoders as -q:v (1 to 100). Each scale is its own: the same number means something different on each encoder. A value outside the encoder's range is refused. An encoder outside those seven, such as libvpx-vp9, is refused with quality set. So is a video_codec of "copy", or of NULL under hardware = "none". When fallback = TRUE falls back to software, the value is dropped and the message says so, because it belonged to the hardware encoder's scale. A stream-copying cut (reencode = FALSE) runs no encoder, so it refuses quality too.

audio_stream

The audio track to carry into the output, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. The every-track family reads NULL this way: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each segment's command (TRUE, default) or only compile them (FALSE).

parallel

A logical passed to ffm_batch: cut segments in parallel with furrr (TRUE) or sequentially (FALSE, default). Parallelism follows the active future plan; TRUE under the default sequential plan runs one segment at a time and warns. Set a plan first, e.g. future::plan(future::multisession).

Value

The tibble returned by ffm_batch: one row per segment with its command (and, when run = TRUE, success).

References

https://ffmpeg.org/ffmpeg-utils.html#time-duration-syntax

See Also

ffm_seek(), the pipeline function it uses to cut; ffm_batch(), the runner; has_hardware_encoder() for the hardware argument; segment_video_batch() for the many-file form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# Two segments; run = FALSE compiles one command per segment
segment_video(video, start = c(0, 0.5), end = c(0.5, 1), run = FALSE)

Segment Many Videos From a Jobs Table

Description

Cut segments across many input files from a single jobs tibble. This is the batch (table-driven) form of segment_video(), for when your segments span more than one input. Each row is one segment; the four required columns name its source, destination, and cut points. This is a thin wrapper over ffm_batch: one reproducible compiled command per segment. The glossary in vignette("tidymedia") explains media terms such as codec, keyframe and stream copy.

Usage

segment_video_batch(
  jobs,
  reencode = TRUE,
  video_codec = NULL,
  audio_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per segment and (at least) the columns input (source path), start and end (cut points). Each cut-point column is a numeric column of seconds or a character column with time-duration syntax. Two optional columns are recognized: output (destination path) and reencode (a logical; see the reencode argument). If output is absent, the function derives one per row by appending _<n>.<ext> to each input's basename. The segment number restarts at 1 for each input file (the same rule as segment_video). Two rows given the same output path are refused before any row runs. A video_codec or audio_codec column overrides that argument per row, with NA meaning "leave the codec unset" (the column's way of writing the argument's NULL). An audio_stream column likewise overrides that argument per row, with NA meaning "keep every audio track" (the column's way of writing that argument's NULL). A numeric quality column overrides the quality argument per row (see quality). Any other columns are ignored.

reencode

A logical passed to ffm_seek: cut each segment frame-accurately by re-encoding (TRUE, default) or with a fast, lossless copy that snaps to keyframes (FALSE). See ffm_seek for the trade-off. Applies to every row, unless jobs carries a reencode column, which overrides this argument on a per-row basis.

video_codec

A string naming the output video codec, applied to every row lacking a video_codec column. NULL (default) leaves it unset, so each segment keeps its container's default encoder. A row can resolve to a codec while cutting by stream copy (reencode = FALSE, as an argument or a column). That row is an error, because no encoder runs on that path.

audio_codec

A string naming the output audio codec, applied to every row lacking an audio_codec column. "copy" (default) stream-copies the audio; name an encoder to re-encode it, or NULL to leave the codec unset. A row can resolve to anything but "copy" while cutting by stream copy (reencode = FALSE, as an argument or a column). That row is an error. So split a jobs table that mixes stream-copy rows with a re-encoding audio_codec into separate calls.

hardware, fallback

The encoder backend and its fallback behavior, applied to the whole batch. They are a property of the machine, not of a row, so neither is read as a jobs column. See segment_video(). Because hardware is batch-wide, a non-"none" value conflicts with a stream-copy row on its own, even one naming no codec. So split a jobs table that mixes reencode = FALSE rows with GPU encoding into separate calls. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows. A call can also contradict itself by asking for GPU encoding on a cut that stream-copies. Such a call is refused for the contradiction first, whether or not this machine has the encoder. The stream-copy conflict named under reencode is caught first, so such a call aborts without probing.

quality

A number, or NULL (default), applied to each row unless jobs carries a numeric quality column. In that column, NA leaves that row's encoder default in place, whatever the argument says. The value is the encoder's own rate-control value, passed through unchanged. Each cell is checked against the encoder its own row resolves to. A wrong cell is refused before any row runs, and the error names this function and the row. See segment_video() for the encoders, their flags and ranges, and the values it refuses. A cell on a row that stream-copies (reencode = FALSE) is refused too, because no encoder runs on that row.

audio_stream

The audio track to carry into each output, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The every-track family reads NULL as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each segment's command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical passed to ffm_batch: cut segments in parallel with furrr (TRUE) or sequentially (FALSE, default). Parallelism follows the active future plan; TRUE under the default sequential plan runs one segment at a time and warns. Set a plan first, e.g. future::plan(future::multisession).

...

Additional arguments forwarded to ffm_batch, such as verify, manifest, checksums, and progress.

Value

The tibble returned by ffm_batch: jobs with an added command column. When output was derived, it also has the resolved output column. When run = TRUE, it has a success column, plus any columns the forwarded arguments add, such as verified.

References

https://ffmpeg.org/ffmpeg-utils.html#time-duration-syntax

See Also

segment_video() for the single-input, parallel-vector form. ffm_batch() for the batch runner and the arguments forwarded through .... has_hardware_encoder() for the hardware argument. ffm_seek() for the cut trade-off.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(
  input  = c(video, video),
  output = c("a.mp4", "b.mp4"),
  start  = c(0, 0.5),
  end    = c(0.5, 1)
)
# run = FALSE compiles one command per segment without calling FFmpeg
segment_video_batch(jobs, run = FALSE)

Split a media file into separate audio and video files

Description

By default, each stream is copied, not re-encoded (audio_codec = "copy", video_codec = "copy"). A copy loses no quality and is fast. Each output container must then support the source codec. For example, write AAC audio from an MP4 to .aac or .m4a, not to .mp3. To re-encode a stream, name an encoder (audio_codec = "libmp3lame"). Pass NULL to set no codec option, so the output extension picks the encoder. Each argument governs only its own output file. Where the video is re-encoded, hardware = "nvenc" or "videotoolbox" moves that encode onto a GPU. The audio output is never affected. The glossary in vignette("tidymedia") explains media terms such as codec, container and stream copy.

Usage

separate_audio_video(
  infile,
  audiofile,
  videofile,
  audio_codec = "copy",
  video_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a media file.

audiofile

A string containing the path of the audio file to write.

videofile

A string containing the path of the video file to write.

audio_codec

A string that names the encoder for audiofile. It goes to FFmpeg's -codec:a. The default "copy" copies the audio stream with no quality loss. A codec name (e.g. "libmp3lame") re-encodes it. NULL sets no -codec:a, so the audiofile extension picks the encoder.

video_codec

A string that names the encoder for videofile. It goes to FFmpeg's -codec:v. The default "copy" copies the video stream with no quality loss. A codec name (e.g. "libx264") re-encodes it. NULL sets no -codec:v, so the videofile extension picks the encoder.

hardware

The encoder backend for videofile. "none" (default) uses the software video_codec. "nvenc" uses NVIDIA GPU encoding, and "videotoolbox" uses Apple GPU encoding. Each uses its own encoder for the family of video_codec. For example, "libx264" becomes "h264_nvenc" or "h264_videotoolbox". With video_codec = NULL, the family is H.264. Only video is encoded on the GPU, so this never affects audiofile. The default video_codec = "copy" is a stream copy, which runs no encoder at all. So a hardware other than "none" with video_codec = "copy" is an error. Name an encoder or pass video_codec = NULL. See has_hardware_encoder for availability and its caveats. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. The stream-copy conflict above is caught first, so such a call aborts without asking FFmpeg.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE encodes in software with a message. FALSE (default) aborts instead. With video_codec = NULL, the fallback leaves the codec unset rather than injecting one. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default) to leave the encoder's own default in place. It is the encoder's own rate-control value, passed through unchanged. libx264 and libx265 read it as -crf (0 to 51). The nvenc encoders read it as -cq (0 to 51), and the videotoolbox encoders as -q:v (1 to 100). Each scale is its own: the same number means something different on each encoder. A value outside the encoder's range is refused. An encoder outside those seven, such as libvpx-vp9, is refused with quality set. So is a video_codec of "copy", or of NULL under hardware = "none". When fallback = TRUE falls back to software, the value is dropped and the message says so, because it belonged to the hardware encoder's scale. It applies to videofile only.

audio_stream

The audio track to write to audiofile, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) keeps every audio track. The every-track family reads NULL this way: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. A container that holds several audio streams (.mka, .m4a) gets them all. A container for one stream only (.aac, .mp3, .wav) makes FFmpeg fail, so name a track to write one of those. Count only the input's audio streams. Do not use the index column of probe_audio, which counts every stream. An input with no audio at all is an FFmpeg error here, because this function writes an audio file. Functions that write only a video file, such as standardize_video, do not fail in that case. videofile is never affected. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run the commands through FFmpeg (TRUE, default) or return the compiled commands without running them (FALSE).

Value

A named character vector of the two compiled commands (audio, video). It is invisible when run = TRUE. Under run = TRUE, the audio command runs first and the video command runs second. The video command runs whether or not the audio command succeeded. A failed audio command still aborts the call. By then, the video command has written videofile, unless it failed too. See When the audio output fails.

When the audio output fails

The two commands run in order: audio first, video second. The video command runs even when the audio command failed, so a failed audio half does not cost you the video. In that case, the call still aborts with the audio failure. That error carries one added line that names the video file that was written. When the video command fails too, the added line is not there. The audio failure is still the error you get. FFmpeg's own output for the failed video command is printed above it.

A time limit reached on the audio command is held like any other audio failure, so the video command still runs. The video command gets a fresh limit of its own, because with_timeout() limits each program that the call starts, not the call. So a call whose audio half reaches the limit can wait up to two limits, not one.

A failed command treats its own output path by the same rule on either path. It removes a partial file that the run wrote. It leaves a file that was already at that path, and that FFmpeg never wrote to, exactly as it was. So neither failure path promises that the path is empty afterwards. It promises only that nothing half-written is left there. The audio failure's own error says which of the two happened to audiofile. The same error's tm_video_error field says what became of the video command. It holds the condition that command raised when it failed too, and NULL when it succeeded.

The default keeps every audio track. So FFmpeg fails when it writes a multi-track input to a container that holds only one track (.aac, .mp3, .wav). When that happens, the error also reports how many audio tracks infile carries, and it names the two ways out. Use audio_stream to write one track, or use a container such as .mka or .m4a to keep them all.

The error carries that extra report only when all four of these hold:

Those containers are .mka, .m4a, .mp4, .mov, .mkv, .webm, .ogg, .opus and .ts. The nine are an exclusion list and not a survey. FFmpeg writes several audio streams into other containers too, .avi and .nut among them. A failure on one of those still gets the report. The container condition keeps the report off a call that already does what the report advises. When a call writes to one of the nine, the failure cannot be the container refusing a second audio stream. The report would then leave unnamed whatever FFmpeg did object to.

If any of the four does not hold, the error you get is the one the run itself raised, whatever that error is. It has the same class, the same status field and the same message. The one difference is the line saying that the video output was written. A failing audio half carries that line when the video command wrote its file and the audio failure is an rlang condition. When the exit status is the one that does not hold, there is no exit status to carry. A run that never reached FFmpeg has none.

The report states what the call did: the track count, and that every track was mapped into one output. It never states why FFmpeg refused. FFmpeg's own error and exit status are printed beneath it and carried on the condition. They remain the only authority on the cause. Several causes look alike from here. A stream copy into a container that will not hold the source codec fails on a multi-track input too. The default audio_codec = "copy" into .mp3 is one example. An unknown encoder and a missing output directory fail the same way.

The condition carries two class names, so a caller can catch it at either width. It is tidymedia_ffmpeg_exit, the class that every non-zero FFmpeg exit raises. An exit-status handler catches that class, and the number is on the condition's tm_status field. It is also tidymedia_multitrack_separation, the class of this report itself. Catch that class when it is this failure in particular you want:

tryCatch(
  separate_audio_video("three-tracks.mkv", "audio.mp3", "video.mp4"),
  tidymedia_ffmpeg_exit = function(cnd) cnd$tm_status
)

When the report is omitted, the error that reaches the caller is the one the run itself raised, apart from that video-output line. A non-zero exit still answers to tidymedia_ffmpeg_exit. A failure that is not an exit answers to neither class here. An FFmpeg that the package cannot locate raises an error with no tidymedia_ class at all. A reached limit raises tidymedia_timeout.

Counting the tracks means running FFprobe, so the report is not guaranteed. The error has it when FFprobe is available and infile can be probed. Otherwise the package omits it silently and leaves FFmpeg's own error alone. So the report may not appear, and its absence is never itself a second failure. The count never runs under run = FALSE and never changes the compiled commands. It is skipped when audio_stream names a track, or when audiofile names one of the multi-stream containers above. With one track mapped, the track count cannot be what FFmpeg objected to.

See Also

ffm_map() and ffm_codec(), the pipeline functions it wraps. has_hardware_encoder() for the hardware argument. extract_audio() to pull out just the audio. probe_audio() to list an input's audio tracks.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video_batch(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
separate_audio_video(video, "audio.aac", "video.mp4", run = FALSE)
# transcode the audio to MP3 while copying the video through untouched
separate_audio_video(video, "audio.mp3", "video.mp4",
                     audio_codec = "libmp3lame", run = FALSE)
# write only the second audio track (this sample has one, so compile only)
separate_audio_video(video, "audio.aac", "video.mp4",
                     audio_stream = 1, run = FALSE)

Separate Audio and Video for Many Files From a Jobs Table

Description

Split the audio and video streams of many input files from a single jobs tibble. This is the batch (table-driven) form of separate_audio_video(), for when you have more than one file. Each row is one input that gives two outputs. The input, audiofile and videofile columns are all required. The function is a thin wrapper over ffm_batch. It turns every input row into two single-output jobs, one per stream. So a jobs table of N rows returns 2N rows, with one reproducible compiled command per stream. Each stream uses the same map and stream-copy pipeline as separate_audio_video(). The glossary in vignette("tidymedia") explains media terms such as codec, container and stream copy.

Usage

separate_audio_video_batch(
  jobs,
  audio_codec = "copy",
  video_codec = "copy",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input. It has at least an input column (source path), plus audiofile and videofile columns that name the two destinations. All three are required. Like separate_audio_video, this function derives no output paths, because the container extension of a copied stream is the instruction. That extension must match the source codec. No two destinations in a table can be the same path. That covers an audiofile and a videofile in one row, and any two across rows. The function refuses such a table before any row runs. Optional audio_codec and video_codec columns override the arguments of the same name per row. They are character, with NA to set no codec option for that stream. Rows that omit a column fall back to that argument. An optional numeric audio_stream column likewise overrides the audio_stream argument per row. There, NA keeps every audio track in that row's audiofile. A numeric quality column overrides the quality argument per row and applies to that row's videofile (see quality). Any other columns are ignored, with one exception. A reencode column, retired with the argument of the same name, is an error and not a silent no-op.

audio_codec

A string that names the encoder for every audiofile, unless jobs carries an audio_codec column. The default "copy" copies the audio stream with no quality loss. NULL sets no -codec:a. See separate_audio_video.

video_codec

A string that names the encoder for every videofile, unless jobs carries a video_codec column. The default "copy" copies the video stream with no quality loss. NULL sets no -codec:v. See separate_audio_video.

hardware, fallback

The encoder backend for every videofile and its fallback behavior. They apply to the whole batch. They are a property of the machine, not of a row, so neither is read as a jobs column. See separate_audio_video(). hardware is batch-wide, and a stream copy runs no encoder. So a hardware other than "none" conflicts with any row whose video codec resolves to "copy". That includes the default. So split a jobs table that mixes copied and re-encoded video into separate calls. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows. A call can also contradict itself by asking for GPU encoding alongside a stream copy. Such a call is refused for the contradiction first, whether or not this machine has the encoder. The stream-copy conflict above is caught first, so such a call aborts without asking FFmpeg.

quality

A number, or NULL (default), applied to every videofile unless jobs carries a numeric quality column. In that column, NA leaves that row's encoder default in place, whatever the argument says. The value is the encoder's own rate-control value, passed through unchanged. Each cell is checked against the encoder its own row resolves to. A wrong cell is refused before any row runs, and the error names this function and the row. See separate_audio_video() for the encoders, their flags and ranges, and the values it refuses. The audiofile never takes it. A cell on a row whose video codec is "copy", the default, is refused, because no encoder runs.

audio_stream

The audio track to write to each audiofile, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) keeps every audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The every-track family reads NULL as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. A container that holds several audio streams (.mka, .m4a) gets them all. A container for one stream only (.aac, .mp3, .wav) makes FFmpeg fail, so name a track to write one of those. Count only the input's audio streams. Do not use the index column of probe_audio, which counts every stream. An input with no audio at all is an FFmpeg error here, because this function writes an audio file. Functions that write only a video file, such as standardize_video, do not fail in that case. videofile is never affected. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical: process the jobs in parallel with furrr (TRUE) or one at a time (FALSE, default). See ffm_batch for the future plan requirement.

...

Additional arguments forwarded to ffm_batch (e.g. verify, manifest, progress).

Value

A tibble with two rows per input, one per stream. It has the reshaped input, a single output path, a stream marker ("audio" or "video"), and an added command column. When run = TRUE, it also has a success column. A run also gives verified and the provenance manifest, each when requested via .... When jobs supplies either codec column, a single codec column carries each row's resolved encoder for its own stream (NA where none is set). When audio_stream is supplied as either the argument or a jobs column, an audio_stream column likewise carries each row's resolved track. That is the selected index on an audio row. It is NA on every video row, which takes no audio, and on an audio row that named no track. So NA does not by itself mark a video row. Read the stream column for that. The columns match the output of the other _batch functions, plus the stream marker. See ffm_batch.

Failed audio outputs

A row whose audio command does not finish cleanly is recorded as success = FALSE, and the batch does not abort. One warning for the whole batch, emitted once, names such rows. It lists every affected input row and the ways out.

A row reaches that warning only when all four of these hold:

Those containers are .mka, .m4a, .mp4, .mov, .mkv, .webm, .ogg, .opus and .ts. No exit status is among those conditions, and the difference from separate_audio_video is deliberate. The batch runner records whether a row succeeded and not how. So it records a non-zero exit, a hard error and a reached limit the same way. It treats alike a row put here by any of them. The nine are an exclusion list and not a survey. FFmpeg writes several audio streams into other containers too, .avi and .nut among them. A row that fails on one of those is still named. The container condition keeps a row off the list when it already does what the warning advises. Such a row is silently not named. A batch whose failed audio rows all write to those nine does not warn at all. The headline count follows the rows actually named.

Each bullet of the warning states what that row did: its track count, and that every track was mapped into one output. It never states why FFmpeg refused. Several causes look alike from here. Examples are a stream copy into a container that will not hold the source codec, an unknown encoder and a missing output directory.

The check runs FFprobe on the failed rows only. So the function emits the warning when FFprobe is available and the input can be probed, and skips it silently otherwise. The warning may not appear, and its absence is never itself a second failure. The check never runs under run = FALSE and never changes any compiled command. Suppress the warning with suppressWarnings(classes = "tidymedia_multitrack_separation").

The warning names the same event as the error of separate_audio_video and answers to the same class. But it carries no exit status: no tm_status field, and no tidymedia_ffmpeg_exit class. The batch runner records, per row, whether the row succeeded, not how FFmpeg exited. The success column holds that record. So the exit number is gone by the time this warning is assembled. To catch a specific row's exit status, use separate_audio_video().

See Also

separate_audio_video(), the one-file function it wraps. ffm_batch(), the batch runner. has_hardware_encoder() for the hardware argument. segment_video_batch() for the other batch function where one input file can give several outputs.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), standardize_video(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), standardize_video(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(
  input     = c(video, video),
  audiofile = c("a1.aac", "a2.aac"),
  videofile = c("v1.mp4", "v2.mp4")
)
# run = FALSE compiles two commands per input without calling FFmpeg
separate_audio_video_batch(jobs, run = FALSE)

Set the location of a dependency program

Description

set_program() saves the location of a program, so the package can find it in later sessions. set_ffmpeg(), set_ffprobe(), set_ffplay() and set_mediainfo() do the same for one program each.

The location goes in a file named after the program, such as ffmpeg_location.txt. The file is under tools::R_user_dir("tidymedia", "config"). find_ffmpeg() and the other ⁠find_*()⁠ functions read it when the program is not on the PATH.

Usage

set_program(
  program = c("ffmpeg", "ffprobe", "ffplay", "mediainfo"),
  location,
  confirm = TRUE
)

set_mediainfo(location, confirm = TRUE)

set_ffmpeg(location, confirm = TRUE)

set_ffprobe(location, confirm = TRUE)

set_ffplay(location, confirm = TRUE)

Arguments

program

A string naming the program to set the location for.

location

A string with the location of the program.

confirm

Whether to ask before the call writes the location. TRUE, the default, asks. In a session where no one can answer, TRUE gives an error. FALSE writes without asking.

Details

The file stays after the session ends, so the call asks you to confirm first. It writes nothing until you agree. The question shows the location as you typed it, which is what the call writes. It also shows the full path of the file. If you say no, the call changes nothing.

In a session where no one can answer, the call gives an error. Pass confirm = FALSE to write without the question, for example in a script that runs on its own.

For locations saved by versions before 0.2.0, see the section "Locations saved by earlier versions" in find_ffmpeg().

Value

Invisibly, TRUE when the call wrote the location and FALSE when you said no.

See Also

find_ffmpeg() and the other ⁠find_*()⁠ functions to find a program, and install_on_win() to download FFmpeg on Windows.

Other program management functions: find_ffmpeg(), install_on_win(), program_status(), unset_program()

Examples

## Not run: 
# Point tidymedia at a binary in a non-standard location; asks first
set_mediainfo("C:/Program Files/MediaInfo/mediainfo.exe")

# In an unattended script, where there is no one to ask
set_mediainfo("C:/Program Files/MediaInfo/mediainfo.exe", confirm = FALSE)

## End(Not run)

Standardize a video to a reproducible format

Description

Re-encode a video to a consistent, reproducible format for analysis. The format is one video codec and pixel format, and optionally a resolution and frame rate, with +faststart for smooth playback. format_for_web uses a fixed recipe for web delivery. Here, every part of the standard is an argument. So a lab can set its own house format once and apply it across a dataset. The glossary in vignette("tidymedia") explains media terms such as codec, pixel format and frame rate.

Usage

standardize_video(
  infile,
  outfile,
  width = NULL,
  height = NULL,
  fps = NULL,
  video_codec = "libx264",
  audio_codec = "copy",
  pixel_format = "yuv420p",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE
)

Arguments

infile

A string containing the path to a video file.

outfile

A string containing the path of the video file to write.

width

The output width in pixels (a positive number), or NULL (default) to leave the width unconstrained.

height

The output height in pixels (a positive number), or NULL (default) to leave the height unconstrained.

fps

The output frame rate (a positive number or FFmpeg framerate expression such as "30000/1001"), or NULL (default) to keep the input frame rate.

video_codec

A string naming the output video codec (default "libx264"). NULL emits no -codec:v and lets the output container's default encoder decide. NULL is how you opt out of the H.264 default for a container that does not hold it. For a .webm output, pass video_codec = NULL and audio_codec = NULL, because the default audio_codec = "copy" would otherwise carry a codec WebM cannot hold.

audio_codec

A string naming the output audio codec. The default "copy" stream-copies the source audio unchanged. Name a real encoder, such as "aac", when the source audio codec cannot be copied into the output container. NULL emits no -codec:a and lets the container's default encoder decide.

pixel_format

A string naming the output pixel format (default "yuv420p").

hardware

The encoder backend. "none" (default) uses the software video_codec. "nvenc" uses NVIDIA GPU encoding (H.264, HEVC and AV1), and "videotoolbox" uses Apple GPU encoding (H.264 and HEVC). A backend uses its own encoder for the family of video_codec. For example, "libx264" becomes "h264_nvenc" or "h264_videotoolbox". See has_hardware_encoder for availability and its caveats. This applies to video only. audio_codec is never hardware-accelerated. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE re-encodes with the software video_codec and a message. FALSE (default) aborts instead. This keeps output reproducible by never changing the codec silently. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default) to leave the encoder's own default in place. It is the encoder's own rate-control value, passed through unchanged. libx264 and libx265 read it as -crf (0 to 51). The nvenc encoders read it as -cq (0 to 51), and the videotoolbox encoders as -q:v (1 to 100). Each scale is its own: the same number means something different on each encoder. A value outside the encoder's range is refused. An encoder outside those seven, such as libvpx-vp9, is refused with quality set. So is a video_codec of "copy", or of NULL under hardware = "none". When fallback = TRUE falls back to software, the value is dropped and the message says so, because it belonged to the hardware encoder's scale.

audio_stream

The audio track to carry into the output, as a number that counts from 0 among the audio tracks of the input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. The every-track family reads NULL this way: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Details

The default standard, standardize_video(infile, outfile), re-encodes to H.264 video (video_codec = "libx264") with pixel_format = "yuv420p" and -movflags +faststart. It keeps the source resolution and frame rate. Audio is stream-copied unchanged (-c:a copy) unless audio_codec names an encoder. The same input therefore always compiles to a byte-identical command. Loudness standardization is out of scope. For that, see normalize_audio.

Resolution follows width and height:

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

ffm_scale(), ffm_codec(), and ffm_pixel_format(), among the pipeline functions it wraps; has_hardware_encoder() for the hardware toggle; standardize_video_batch() for the many-file form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video_batch(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
# The documented default standard (H.264 / yuv420p / +faststart)
standardize_video(video, "std.mp4", run = FALSE)
# Pin resolution and frame rate too
standardize_video(video, "std.mp4", width = 1280, height = 720, fps = 30,
                  run = FALSE)
# Carry only the second audio track instead of all of them
standardize_video(video, "std.mp4", audio_stream = 1, run = FALSE)

Standardize Many Videos From a Jobs Table

Description

Re-encode many files to a reproducible format, using one jobs table. This is the batch form of standardize_video(), for when you have more than one video to standardize. Each row is one input, and the only required column names its source. The function is a thin wrapper over ffm_batch. It builds one reproducible command for each input. The glossary in vignette("tidymedia") explains media terms such as codec, pixel format and frame rate.

Usage

standardize_video_batch(
  jobs,
  width = NULL,
  height = NULL,
  fps = NULL,
  video_codec = "libx264",
  audio_codec = "copy",
  pixel_format = "yuv420p",
  hardware = c("none", "nvenc", "videotoolbox"),
  fallback = FALSE,
  quality = NULL,
  audio_stream = NULL,
  run = TRUE,
  parallel = FALSE,
  ...
)

Arguments

jobs

A data frame with one row per input. It needs at least an input column, the source path. An optional output column names the destination. Without it, each row's output name adds _standardized to the input's base name and keeps its extension. For example, clip.mkv becomes clip_standardized.mkv. Two rows naming the same output path are refused before any row runs. That is a path repeated in the output column, or a repeated input when there is no output column. A column can override any of the six format arguments for each row: width, height, fps, video_codec, audio_codec and pixel_format. An argument with no column applies its value to every row. In either codec column, NA leaves that row's codec unset. That is the column form of video_codec = NULL or audio_codec = NULL. In a width, height, fps or pixel_format column, NA is an error. pixel_format has no unset state to express. width, height and fps do accept NULL as arguments, but their columns have no NA form for it. An audio_stream column overrides the audio_stream argument for each row, and NA keeps that row on every audio track. A numeric quality column overrides the quality argument per row (see quality). Any other columns are ignored.

width, height

Optional target dimensions for every row, unless jobs has a column of the same name (see jobs). When only one is given, the other is derived to keep the aspect ratio. When neither is given, the frame is floor-cropped to even dimensions, so odd-sized sources encode. (default = NULL)

fps

Optional target frame rate applied to every row, unless jobs carries an fps column. (default = NULL, i.e. leave the frame rate unchanged)

video_codec

A string naming the video codec for every row, unless jobs has a video_codec column. In that column, NA leaves that row's codec unset. The default is "libx264". NULL emits no -codec:v and lets the output container's default encoder decide. For a .webm output, pass audio_codec = NULL too, because the default "copy" would otherwise carry a codec WebM cannot hold.

audio_codec

A string naming the audio codec for every row, unless jobs has an audio_codec column. In that column, NA leaves that row's codec unset. "copy" (default) stream-copies the audio through untouched. Name an encoder, such as "aac", when the source audio cannot be copied into the output container.

pixel_format

A string naming the pixel format applied to every row, unless jobs carries a pixel_format column. (default = "yuv420p")

hardware

The encoder backend for every row. "none" is the default. "nvenc" uses NVIDIA GPU encoding (H.264, HEVC and AV1), and "videotoolbox" uses Apple GPU encoding (H.264 and HEVC). It applies to the whole batch and is not read as a column. See standardize_video and has_hardware_encoder. Resolving a hardware backend asks this FFmpeg build which encoders it has. So the first such call that re-encodes the video runs FFmpeg while the command is built, even under run = FALSE. The answer is remembered for the rest of the R session. See refresh_ffmpeg_capabilities to discard it. This function checks that the encoder is available before any row runs. So an unavailable encoder aborts naming this function, not the internal step that runs the rows.

fallback

A logical. When a hardware other than "none" is requested but its encoder is unavailable, TRUE re-encodes with the software video_codec and a message. FALSE (default) aborts instead. A video_codec in a family that the backend has no encoder for is a wrong argument, not an absent encoder. So it aborts whatever fallback says.

quality

A number, or NULL (default), applied to each row unless jobs carries a numeric quality column. In that column, NA leaves that row's encoder default in place, whatever the argument says. The value is the encoder's own rate-control value, passed through unchanged. Each cell is checked against the encoder its own row resolves to. A wrong cell is refused before any row runs, and the error names this function and the row. See standardize_video() for the encoders, their flags and ranges, and the values it refuses.

audio_stream

The audio track to carry into each output, as a number that counts from 0 among the audio tracks of each row's input. 0 is the first audio track and 1 is the second. Other streams in the file, such as video, do not count. NULL (default) carries every audio track. Without an audio_stream column, the argument applies to every row. An NA cell in that column means NULL for that row. It does not fall back to the argument. The every-track family reads NULL as every audio track: separate_audio_video, standardize_video, anonymize_video, crop_video, segment_video and format_for_web, and their _batch forms. The first-track family reads it as the first audio track only: extract_audio, convert_audio and normalize_audio, and their _batch forms. The function does not carry subtitle or data streams in either case. A track the input does not have gives an FFmpeg error, not an R one. See audio_stream for how this differs from audio_input, the input index on compare_videos and picture_in_picture. (default = NULL)

run

A logical: run each input's command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical passed to ffm_batch: standardize in parallel with furrr (TRUE) or sequentially (FALSE, default). Parallelism follows the active future plan; TRUE under the default sequential plan runs one input at a time and warns. Set a plan first, e.g. future::plan(future::multisession).

...

Additional arguments forwarded to ffm_batch, such as verify, manifest, checksums, and progress.

Value

The tibble returned by ffm_batch: jobs with an added command column. When output was derived, it also has the resolved output column. When run = TRUE, it has a success column, plus any columns the forwarded arguments add, such as verified.

See Also

standardize_video() for the single-input form; ffm_batch() for the batch runner and the arguments forwarded through ...; segment_video_batch() and extract_frame_batch() for the other batch task functions.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), strip_metadata(), strip_metadata_batch()

Other audio selection functions: anonymize_video(), anonymize_video_batch(), audio_stream, compare_videos(), compare_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(
  input  = c(video, video),
  output = c("a.mp4", "b.mp4"),
  width  = c(640, 320)
)
# run = FALSE compiles one command per input without calling FFmpeg
standardize_video_batch(jobs, run = FALSE)

Strip identifying metadata from a media file

Description

Remove a media file's container and global metadata tags, together with any chapters, and write a de-identified copy. The tags include creation time, GPS or other location, device make and model, title and comment. Use it to de-identify research recordings, for example for an IRB (a research ethics board). The audio and video streams are stream-copied, not re-encoded. So the operation is lossless and fast, and the picture and sound are bit-for-bit unchanged. That includes any rotation display matrix, which is stream side data and not a metadata tag. The glossary in vignette("tidymedia") explains media terms such as container, stream and stream copy.

Usage

strip_metadata(infile, outfile, run = TRUE)

Arguments

infile

A string containing the path to a media file.

outfile

A string containing the path of the de-identified file to write. Use the same container extension as infile so the copied streams remux cleanly.

run

A logical: run the command through FFmpeg (TRUE, default) or return the compiled command without running it (FALSE).

Details

The output is written bit-exactly (-fflags +bitexact). So FFmpeg does not stamp the container again with a fresh creation_time, or with an encoder tag that names its own version. Either tag would defeat de-identification and reproducibility.

Because the streams are copied and not re-encoded, some data is not removed. Those are identifiers inside the encoded bitstream, and per-stream metadata such as handler_name or language. Removing them would require one of two things. One is re-encoding, which is out of scope for this function, so use the direct command ffmpeg for it. The other is per-stream metadata mapping that must probe the file first.

Value

The compiled FFmpeg command (invisibly when run = TRUE).

See Also

anonymize_video() removes faces or regions from the picture, for visual de-identification. probe_container() and mediainfo_query() inspect a file's metadata before and after. This function wraps the pipeline functions ffm_copy() and ffm_output_options(). strip_metadata_batch() is the many-file form.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata_batch()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
strip_metadata(video, "clean.mp4", run = FALSE)

Strip Metadata From Many Files From a Jobs Table

Description

De-identify many files, using one jobs table. This is the batch form of strip_metadata(), for when you have more than one file to scrub. Each row is one input, and the only required column names its source. The function is a thin wrapper over ffm_batch. It builds one reproducible stream-copy strip command for each input. Each command uses the same steps as strip_metadata(), so it is bit-exact and drops the same metadata. The glossary in vignette("tidymedia") explains media terms such as stream and stream copy.

Usage

strip_metadata_batch(jobs, run = TRUE, parallel = FALSE, ...)

Arguments

jobs

A data frame with one row per input. It needs at least an input column, the source path. An optional output column names the destination. Without it, each row's output name adds _stripped to the input's base name and keeps its extension. For example, clip.mkv becomes clip_stripped.mkv. Any two rows with the same output path are rejected, so one file cannot silently overwrite another. That happens with a duplicated input and no output column, or with a repeated explicit output. Any other columns are ignored, because the scrub has no per-row settings.

run

A logical: run each input's command through FFmpeg (TRUE, default) or only compile them for inspection (FALSE).

parallel

A logical passed to ffm_batch: scrub in parallel with furrr (TRUE) or sequentially (FALSE, default). Parallelism follows the active future plan; TRUE under the default sequential plan runs one input at a time and warns. Set a plan first, e.g. future::plan(future::multisession).

...

Additional arguments forwarded to ffm_batch, such as verify, manifest, checksums, and progress.

Value

The tibble returned by ffm_batch: jobs with an added command column. When output was derived, it also has the resolved output column. When run = TRUE, it has a success column, plus any columns the forwarded arguments add, such as verified.

See Also

strip_metadata() for the single-input form; ffm_batch() for the batch runner and the arguments forwarded through ...; standardize_video_batch() and anonymize_video_batch() for the other batch task functions.

Other task functions: anonymize_video(), anonymize_video_batch(), compare_videos(), compare_videos_batch(), concatenate_videos(), concatenate_videos_batch(), convert_audio(), convert_audio_batch(), crop_video(), crop_video_batch(), extract_audio(), extract_audio_batch(), extract_frame(), extract_frame_batch(), format_for_web(), format_for_web_batch(), normalize_audio(), normalize_audio_batch(), picture_in_picture(), picture_in_picture_batch(), sample_frames(), sample_frames_batch(), segment_video(), segment_video_batch(), separate_audio_video(), separate_audio_video_batch(), standardize_video(), standardize_video_batch(), strip_metadata()

Examples

video <- system.file("extdata", "sample.mp4", package = "tidymedia")
jobs <- tibble::tibble(input = video, output = "clean.mp4")
# run = FALSE compiles one command per input without calling FFmpeg
strip_metadata_batch(jobs, run = FALSE)

Tidy eval helpers

Description

The .data pronoun is reexported from rlang. It represents the current slice of data inside data-masking verbs. If you have a column name stored in a string, use .data[["var"]] to refer to that column. See the rlang reference for details.

Value

This page documents no function and returns no value. .data is not called either: it is an object, of class rlang_fake_data_pronoun, that has meaning only inside a data-masking verb, where it stands for the current slice of data. Subsetting it there, as .data[["var"]], gives that column.


Forget the location of a dependency program

Description

unset_program() forgets the location that set_program() saved for a program. After that, find_ffmpeg() and the other ⁠find_*()⁠ functions look for the program on the PATH only.

Usage

unset_program(program)

Arguments

program

A string naming the program to forget. One of "ffmpeg", "ffprobe", "ffplay" or "mediainfo". There is no default, because the call deletes a file. A call that names no program gives an error.

Details

The call deletes the file that holds the location. It does not ask you to confirm first. It does not remove the program, and it does not change the PATH. A program on the PATH is still found afterwards.

If no location is saved for the program, the call gives a warning and returns FALSE. It does not give an error, because the program is already forgotten.

The call also clears a location saved by a version before 0.2.0. See the section "Locations saved by earlier versions" in find_ffmpeg().

Value

Invisibly, TRUE when the call removed a saved location, and FALSE when there was none to remove.

See Also

set_program() to save a location, and program_status() to see where the package finds each program.

Other program management functions: find_ffmpeg(), install_on_win(), program_status(), set_program()

Examples

## Not run: 
# Forget a location set_program() remembered, so that find_mediainfo() goes
# back to answering from the PATH
unset_program("mediainfo")

## End(Not run)

Verify a Media File Against Expected Properties

Description

Probe a media file and check its structural metadata against a set of expectations, returning a tidy pass/fail tibble with one row per checked property. A reproducible command tells you what ran. This function tells you whether the result is what you asked for. Use it after a conversion to confirm that the output has the duration, dimensions, codecs and other properties the pipeline was meant to produce.

Usage

verify_media(
  file,
  duration = NULL,
  width = NULL,
  height = NULL,
  video_codec = NULL,
  audio_codec = NULL,
  sample_rate = NULL,
  ...,
  tolerance = 0.1
)

Arguments

file

A string naming a single media file to verify.

duration

Expected container duration in seconds (numeric).

width, height

Expected video-frame dimensions in pixels (numeric).

video_codec, audio_codec

Expected codec names for the first video and audio stream (strings, e.g. "h264", "aac").

sample_rate

Expected audio sample rate in Hz (numeric).

...

Further expectations given as name = value, each checked against the FFprobe field of that name (container first, then video, then audio).

tolerance

The absolute tolerance for numeric checks (default 0.1).

Details

The glossary in vignette("tidymedia") explains media terms such as codec, stream and keyframe.

Checks are structural (drawn from FFprobe metadata), not perceptual: this does not measure visual or audio quality. The named arguments cover the most common properties; pass any other FFprobe field by name through ... (for example pix_fmt = "yuv420p" or bit_rate = 141800). Extra names are resolved against the probe columns in the order container, then video stream, then audio stream, and the first match wins.

Numeric checks pass when abs(actual - expected) <= tolerance. With the default tolerance of 0.1, whole-number properties (width, height, sample rate) must match exactly. The duration check allows a small difference, for example for cuts that snap to a keyframe. String checks (the codecs) must match exactly. A property whose stream or column is absent yields an NA actual value and a failing check.

Value

A tibble with one row per checked property and columns file, check, expected, actual, and pass (logical).

See Also

ffm_run() and ffm_batch(), which accept a ⁠verify =⁠ spec.

Other verification functions: ffm_manifest()

Examples


video <- system.file("extdata", "sample.mp4", package = "tidymedia")
verify_media(video, width = 320, height = 240, video_codec = "h264")


Set a time limit for one call

Description

with_timeout() runs expr with a time limit of its own. The limit applies to each FFmpeg, FFprobe or MediaInfo program that expr starts. When with_timeout() returns, or stops with an error, the limit that was in force before the call is back.

The session limit, options(tidymedia.timeout = ), applies to every call in the session. with_timeout() applies to one call. For example, you can give one test conversion five minutes in a session with a one-hour limit.

Usage

with_timeout(expr, seconds)

Arguments

expr

An expression. It is run once, where you wrote it, and its value is returned.

seconds

A whole number of seconds. 0 means no limit, so with_timeout(expr, 0) removes a session limit for one call. A fraction, a negative number, a string or NULL gives an error before expr runs.

Details

The limit applies to each program, not to the whole call. In a 100-row batch inside with_timeout(expr, 600), each program that a row starts gets 600 seconds, plus the delay in "How long the wait can be". The workers of a parallel = TRUE run use the same limit.

The limit is a whole number of seconds. The package does not round a fraction, because R would read a limit below one second as no limit.

A limit set with options(tidymedia.timeout = ) follows the same rule, with one difference. options(tidymedia.timeout = NULL) removes the option, so it means no limit. A function that can start a program gives an error for a wrong value, even when run = FALSE. ffm_batch() gives that error before it starts any job. A function that starts no program gives no such error. For example, has_hardware_encoder() starts none when you set tidymedia.hardware_encoders. A ⁠probe_*()⁠ function that you give a probe object also starts none.

Most functions check their own arguments before the limit. So a wrong argument gives its own error, even when the limit is also wrong. A few arguments of the ⁠_batch⁠ functions are checked inside each job, after the limit. An example is the pixel_format of anonymize_video_batch(). When the limit is also wrong, the error is about the limit.

Value

The value of expr.

How long the wait can be

The limit sets how long R waits for a program, and the wait can be longer. When the limit is reached, R asks the program to stop. R asks again 20 seconds later, and kills the program 20 seconds after that. So R can wait up to 40 seconds past the limit. For example, five hung files under a 1-second limit can take about three and a half minutes.

R does not guarantee that the program stops. A program can survive the attempts to stop it. How fast a program stops also depends on its version.

What happens when the limit is reached

A reached limit is never silent. The call gives an error or a warning.

These functions give an error with the class tidymedia_timeout, which names the program and the limit:

These functions give a warning instead, so that one hung file does not lose the rest of the work:

suppressWarnings(classes = "tidymedia_dropped_audio") hides the dropped-track warning, but not the warning that the check timed out. To hide both, add "tidymedia_probe_timeout" to classes.

The task functions and ffm_run() delete a part-written output file after a timeout, as they do after any failed run. ffmpeg() cannot tell which of your arguments is the output, so it leaves that file. Check the output of a timed-out ffmpeg() call yourself.

See Also

local_timeout() to set a limit for the rest of a function. tidymedia-package describes the session options.

Examples

# Inside the call, the limit is the one you gave.
with_timeout(getOption("tidymedia.timeout"), 30)

# Outside it, the session's own setting is untouched.
getOption("tidymedia.timeout", default = "unset")


# Bound one conversion at five minutes, whatever the session is set to.
# Needs FFmpeg, and writes to a temporary file.
if (nzchar(Sys.which("ffmpeg"))) {
  video <- system.file("extdata", "sample.mp4", package = "tidymedia")
  with_timeout(extract_audio(video, tempfile(fileext = ".wav")), 300)
}