---
title: "Quick start"
output:
rmarkdown::html_vignette:
tabset: true
vignette: >
%\VignetteIndexEntry{Quick start}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(
echo = TRUE,
collapse = TRUE,
comment = "#>"
)
```
The `fathom` package allows R users to qualitatively code and measure a corpus of text, images, audio, or video with local large language models (LLMs), where every answer comes back as a probability rather than a word. This page helps you install the package, confirm that your Ollama server is up and running, and configure the additional software tools required to evaluate an audio or video corpus.
## Installation
`fathom` is distributed through R-Universe.
```{r install, eval=FALSE}
install.packages(
"fathom",
repos = c("https://alcocer-jj.r-universe.dev", "https://cloud.r-project.org")
)
```
You also need a running [Ollama](https://ollama.com) server at version 0.12.11 or later and at least one instruction-following model pulled.
Ollama provides a [quick start tutorial](https://docs.ollama.com/quickstart) on how to get set up.
Ollama runs on macOS, Windows, and Linux.
## Tested Ollama models
The following Ollama models were tested for compatibility.
Table of models tested
Because Ollama does not broadly support native audio and video input yet, audio and video corpora rely on text and image capabilities through the `prepare_audio()` and `prepare_video()` functions.
| Model | Parameter | Text | Image |
|---|---|---|---|
| [`deepseek-llm`](https://ollama.com/library/deepseek-llm) | 7B | Yes | No |
| [`deepseek-v2`](https://ollama.com/library/deepseek-v2) | 16B | Yes | No |
| [`gemma3`](https://ollama.com/library/gemma3) | 4B, 12B, 27B | Yes | Yes |
| [`gemma4`](https://ollama.com/library/gemma4) | 12B, 26B, 31B | Yes | Yes |
| [`granite4.1`](https://ollama.com/library/granite4.1) | 3B, 8B, 30B | Yes | No |
| [`llama3.2`](https://ollama.com/library/llama3.2) | 3B | Yes | No |
| [`mistral`](https://ollama.com/library/mistral) | 7B | Yes | No |
| [`mistral-small`](https://ollama.com/library/mistral-small) | 24B | Yes | No |
| [`mistral-small3.1`](https://ollama.com/library/mistral-small3.1) | 24B | Yes | Yes |
| [`mistral-small3.2`](https://ollama.com/library/mistral-small3.2) | 24B | Yes | Yes |
| [`nemotron-cascade-2`](https://ollama.com/library/nemotron-cascade-2) | 30B | Yes | No |
| [`olmo-3.1`](https://ollama.com/library/olmo-3.1) | 32B^[Only the instruct model was tested.] | Yes | No |
| [`qwen3.5`](https://ollama.com/library/qwen3.5) | 9B, 27B | Yes | Yes |
| [`qwen3.6`](https://ollama.com/library/qwen3.6) | 35B | Yes | Yes |
| [`qwen3.8`](https://ollama.com/library/qwen3.8) | 27B | Yes | Yes |
## Checking the server and the model
With Ollama installed and models pulled, `ollama_backend()` confirms the server is answering and the model is there.
If called without a model name, the function lists the models you have installed and their capabilities.
```{r backend-list, eval=FALSE}
ollama_backend()
#> Models on http://localhost:11434
#>
#> deepseek-llm:7b 4.0 GB 7B Q4_0 text
#> deepseek-r1:32b 19.9 GB 32.8B Q4_K_M text
#> deepseek-v2:16b 8.9 GB 15.7B Q4_0 text
#> gemma3:27b 17.4 GB 27.4B Q4_K_M text, image
#> gemma4:31b 19.9 GB 31.3B Q4_K_M text, image
#> granite4.1:30b 17.5 GB 28.9B Q4_K_M text
#> ministral-3:14b 9.1 GB 13.9B Q4_K_M text, image
#> mistral-small:24b 14.3 GB 23.6B Q4_K_M text
#> mistral-small3.2:24b 15.2 GB 24.0B Q4_K_M text, image
#> nemotron3:33b 27.6 GB 33.0B Q4_K_M text, image
#> olmo-3:32b 19.5 GB 32.2B Q4_K_M text
#> olmo-3.1:32b-instruct 19.5 GB 32.2B Q4_K_M text
#> qwen3.5:27b 17.4 GB 27.8B Q4_K_M text, image
#> qwen3.6:35b 23.9 GB 36.0B Q4_K_M text, image
#>
#> Error: `model` is required. Paste one of the tags above, e.g.
#> ollama_backend("deepseek-llm:7b")
```
## Working with an audio or video corpus
The following tools are required if you want to work with an audio or video corpus, as Ollama does not broadly support native audio and video input yet.
### ffmpeg {.tabset}
Both `prepare_audio()` and `prepare_video()` need it.
Video is read through it directly, and the recognizers below load audio through it, so a recording in any format, a bare .wav included, needs it too.
#### macOS
`ffmpeg` can be installed via [Homebrew](https://brew.sh), an open-source package manager that runs in the terminal.^[To set up Homebrew, see their [installation guide](https://docs.brew.sh/Installation). Alternatively, see this external [step-by-step walkthrough](https://nyu-processor-design.github.io/getting_started/development/01_homebrew.html) for a more in-depth guide.]
Run this in a terminal window.
```zsh
brew install ffmpeg
```
Then confirm the installation worked.
```zsh
ffmpeg -version
```
#### Windows
`ffmpeg` can be installed via [WinGet](https://learn.microsoft.com/en-us/windows/package-manager/winget/), Windows' native package manager for the command line.^[WinGet is only supported on Windows 10 version 1809 or later. If you are running an earlier version of Windows or if the installation fails, download `ffmpeg` through their [site](https://www.ffmpeg.org/download.html) and follow the **Manual Installation** steps in this [external guide](https://github.com/oop7/ffmpeg-install-guide).]
Run this in a PowerShell window.
```powershell
winget install -e --id Gyan.FFmpeg
```
Restart the PowerShell window, then confirm the installation worked.
```powershell
ffmpeg -version
```
#### Linux
`ffmpeg` can be installed via [APT](https://wiki.debian.org/Apt), the command-line package manager that Debian and Ubuntu ship with.^[Other distributions use their own package manager; see this [guide to the other distributions](https://itsfoss.com/ffmpeg/) for more information.]
Run this in a terminal window.
```bash
sudo apt install ffmpeg
```
Then confirm the installation worked.
```bash
ffmpeg -version
```
### whisperx {.tabset}
`prepare_audio()` and `prepare_video()` transcribe with [`whisperx`](https://github.com/m-bain/whisperX), which runs on macOS, Windows, or Linux. Alternatively, Apple Silicon users can use [`whispermlx`](https://github.com/KalebJS/whispermlx), the same tool with its inference backend replaced by MLX and optimized for M-series chips. To use it, pass `tool = "whispermlx"`, since `whisperx` is the default.
#### macOS
`whisperx` can be installed via [uv](https://docs.astral.sh/uv/), a package manager that installs Python command-line tools into isolated environments.^[To set up `uv`, see their [installation guide](https://docs.astral.sh/uv/getting-started/installation/), or run `brew install uv` if you already have Homebrew from the section above.]
Run this in a terminal window.
```zsh
uv tool install whisperx # or swap with whispermlx
```
Then confirm the installation worked.
```zsh
whisperx --version # or swap with whispermlx
```
Then, in R, confirm your environment can see it, along with `ffmpeg`.^[An empty string in your console means R was started without that directory on its `PATH`. `uv tool dir --bin` in a terminal window prints where `uv` put the command; paste that path to `~/.Renviron`, which R reads at startup, as `PATH=${PATH}:/the/directory`. `usethis::edit_r_environ()` in an R session opens the file wherever it lives. Restart R afterwards.]
```{r macos-check, eval=FALSE}
Sys.which("whisperx") # or swap with whispermlx
Sys.which("ffmpeg")
```
#### Windows
`whisperx` can be installed via [uv](https://docs.astral.sh/uv/), a package manager that installs Python command-line tools into isolated environments.^[To set up `uv`, see their [installation guide](https://docs.astral.sh/uv/getting-started/installation/), or run `winget install --id=astral-sh.uv -e` and restart the command-line window if you already have WinGet from the section above. For GPU acceleration, install the [CUDA toolkit 12.8](https://developer.nvidia.com/cuda-12-8-1-download-archive) before `whisperx`; CPU-only installs skip it.]
Run this in a PowerShell window.
```powershell
uv tool install whisperx
```
Then confirm the installation worked.
```powershell
whisperx --version
```
Then, in R, confirm your environment can see it, along with `ffmpeg`.^[An empty string in your console means R was started without that directory on its `PATH`. `uv tool dir --bin` in a PowerShell window prints where `uv` put the command; paste that path to `~/.Renviron`, which R reads at startup, as `PATH=${PATH};"C:\the\directory"`. `usethis::edit_r_environ()` in an R session opens the file wherever it lives. Restart R afterwards.]
```{r windows-check, eval=FALSE}
Sys.which("whisperx")
Sys.which("ffmpeg")
```
#### Linux
`whisperx` can be installed via [uv](https://docs.astral.sh/uv/), a package manager that installs Python command-line tools into isolated environments.^[`uv` is not in the Debian or Ubuntu repositories, so the standalone installer is the usual route; see their [installation guide](https://docs.astral.sh/uv/getting-started/installation/). For GPU acceleration, install the [CUDA toolkit 12.8](https://docs.nvidia.com/cuda/cuda-installation-guide-linux/) before `whisperx`; CPU-only installs skip it.]
Run this in a terminal window.
```bash
uv tool install whisperx
```
Then confirm the installation worked.
```bash
whisperx --version
```
Then, in R, confirm your environment can see it, along with `ffmpeg`.^[An empty string in your console means R was started without that directory on its `PATH`. `uv tool dir --bin` in a terminal window prints where uv put the command; add it to `~/.Renviron`, which R reads at startup, as `PATH=${PATH}:/the/directory`. `usethis::edit_r_environ()` in an R session opens the file wherever it lives. Restart R afterwards.]
```{r linux-check, eval=FALSE}
Sys.which("whisperx")
Sys.which("ffmpeg")
```
### HuggingFace read token
Both the `prepare_audio()` and `prepare_video()` functions require a HuggingFace (HF) API token when setting `diarize_names = TRUE`, as the diarization model the package uses is gated. However, transcription, alignment, and voice activity detection all run from ungated weights, so only the labeling of speakers requires that extra step. To get access to the gated model, sign in to your HF account and accept the conditions on the [model webpage](https://huggingface.co/pyannote/speaker-diarization-community-1). Then, create a read token at [hf.co/settings/tokens](https://hf.co/settings/tokens) and add it to your `~/.Renviron` as a line like this one.
```ini
HF_TOKEN=hf_yourtokenhere
```
Restart your R session, confirm that the token is available, and save it to an object to be passed as `hf_token` later.
```{r hf-check, eval=FALSE}
Sys.getenv("HF_TOKEN")
hf_token <- Sys.getenv("HF_TOKEN")
```
## Workflow summary
A full run can consist of five to seven steps depending on whether your corpus of interest is not text and if you want an additional diagnostic check.
0. **Prepare a corpus** with `prepare_image()`, `prepare_audio()` or `prepare_video()`.
1. **Select a model** with `ollama_backend()`.
2. **Code the qualitative instrument** with `instrument()`, and use `preview()` to see what the local LLM will read.
3. **Extract response probabilities** with `measure()`.
4. **Read the results** with `item_report()` for descriptive summaries, use `inspect_cases()` to manually review some entries, and apply `as_wide()` to hand off for downstream analyses.
5. **Validate the LLM results** with `coding_sample()` and `validate_sample()`.
6. **Test the measurement** with `threshold_sensitivity()` to assess if endorsement rates are sensitive to cut-point thresholds.
For an applied example, see [A complete run](complete_run.html).