You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**flowcam** provides a tidy interface to the USGS [National Imagery Management System (NIMS)](https://api.waterdata.usgs.gov/nims/v0), the API that stores and serves images collected by stream-gage cameras across the United States. Discover cameras, list and download images, and assemble them into animated GIFs or MP4 videos — all from R.
4
+
5
+
## Installation
6
+
7
+
```r
8
+
# install.packages("pak")
9
+
pak::pak("ConnorB/flowcam")
10
+
```
11
+
12
+
## Quick start
13
+
14
+
```r
15
+
library(flowcam)
16
+
17
+
# Store your free USGS API key (one-time setup)
18
+
set_nims_key("your_api_key_here")
19
+
20
+
# Find the camera at a USGS monitoring location
21
+
cam<- find_cameras(site_id="08385630")
22
+
23
+
# List the 20 most recent images with timestamps
24
+
list_images(cam$camId, limit=20, raw_item=TRUE)
25
+
26
+
# Download a three-day window to disk
27
+
dest<- file.path(tempdir(), "pecos")
28
+
dir.create(dest)
29
+
30
+
download_images(
31
+
cam_id=cam$camId,
32
+
dest_dir=dest,
33
+
size="small",
34
+
time= c("2025-06-10", "2025-06-12")
35
+
)
36
+
37
+
# Assemble into an animated GIF
38
+
make_gif(dir=dest, fps=3, output="pecos.gif")
39
+
40
+
# Or an MP4 video
41
+
make_video(dir=dest, fps=3, output="pecos.mp4")
42
+
```
43
+
44
+
## Core functions
45
+
46
+
| Function | Description |
47
+
|---|---|
48
+
|`find_cameras()`| Retrieve camera metadata; filter by NWIS site number or camera ID |
49
+
|`find_gage_cameras()`| Like `find_cameras()`, plus NWIS site attributes (drainage area, HUC, state) via **dataRetrieval**|
50
+
|`list_images()`| List image filenames for a camera; filter by time window |
51
+
|`download_images()`| Download images to a local directory; resumes safely if interrupted |
52
+
|`make_gif()`| Assemble images into an animated GIF |
53
+
|`make_video()`| Assemble images into an MP4 video |
54
+
55
+
## Authentication
56
+
57
+
Register for a free key at <https://api.waterdata.usgs.gov/signup/>. Unauthenticated requests work but share a rate-limit pool. Store the key once and it persists across sessions:
58
+
59
+
```r
60
+
set_nims_key("your_api_key_here")
61
+
```
62
+
63
+
`flowcam` uses the same `API_USGS_PAT` environment variable as **dataRetrieval**, so one key covers both packages.
64
+
65
+
## Learn more
66
+
67
+
-[Getting started](articles/getting-started.html) — authentication, discovering cameras, listing images, downloading, and creating GIFs and videos in one walkthrough.
68
+
-[Comparing two Pecos River gages](articles/pecos-river.html) — use `find_gage_cameras()` to enrich camera records with watershed metadata, download images from two sites on the same river reach, and produce a GIF and video to track a flow event moving downstream.
69
+
-[Function reference](reference/index.html) — complete documentation for all exported functions.
**flowcam** provides a tidy interface to the USGS [National Imagery Management System (NIMS)](https://api.waterdata.usgs.gov/nims/v0) API, which serves stream-gage camera images collected across the United States.
20
+
**flowcam** gives you a tidy interface to the USGS [National Imagery Management System (NIMS)](https://api.waterdata.usgs.gov/nims/v0) API—the service that stores and serves images collected by stream-gage cameras across the United States. With a few function calls you can discover cameras, list available images, download them to disk, and stitch them into an animated GIF or MP4 video.
21
+
22
+
Full function reference: <https://connorb.github.io/flowcam/reference/>
23
+
24
+
```{r library}
25
+
library(flowcam)
26
+
```
21
27
22
28
## Authentication
23
29
24
-
NIMS requests can be made without an API key, but unauthenticated calls are rate-limited. Register for a free key at <https://api.waterdata.usgs.gov/signup/> and store it with `set_nims_key()`:
30
+
NIMS requests work without a key, but unauthenticated traffic shares a rate-limit pool across all users. Register for a free key at <https://api.waterdata.usgs.gov/signup/> and store it once with `set_nims_key()`:
25
31
26
32
```{r auth}
27
-
library(flowcam)
28
-
29
33
set_nims_key("your_api_key_here")
30
34
```
31
35
32
-
`set_nims_key()` writes `API_USGS_PAT` to `~/.Renviron` and applies it to the current session immediately. All subsequent API calls in the session—and in future R sessions—use that key automatically. The same environment variable is read by the `dataRetrieval` package, so one key covers both.
36
+
This writes `API_USGS_PAT` to `~/.Renviron` and applies it to the current session immediately. Every subsequent call—in this session and in future R sessions—picks up the key automatically. The `dataRetrieval` package reads the same environment variable, so one key covers both.
37
+
38
+
## Finding cameras
33
39
34
-
## Discovering cameras
40
+
`find_cameras()` returns a tibble of camera metadata. Called with no arguments it fetches every camera currently registered in NIMS:
35
41
36
-
`find_cameras()` returns a tibble of camera metadata. With no arguments it fetches all available cameras; pass `site_id` to narrow results to a specific NWIS site.
42
+
```{r find-all}
43
+
all_cameras <- find_cameras()
44
+
nrow(all_cameras)
45
+
```
37
46
38
-
The Pecos Web Camera near Roswell, NM (NWIS site 08385630) is a well-known site on the Pecos River:
47
+
Narrow to a specific USGS monitoring location by passing its NWIS site number:
39
48
40
-
```{r find-cameras}
49
+
```{r find-by-site}
41
50
cam <- find_cameras(site_id = "08385630")
42
51
cam
43
52
```
44
53
45
-
Key columns returned:
54
+
This returns the Pecos Web Camera near Roswell, NM. The same record is reachable by its camera identifier:
The `time` argument accepts a Date, POSIXct, or ISO 8601 character value. A single value means "on or after":
100
+
101
+
```{r time-single}
102
+
list_images(
103
+
"NM_Pecos_Web_Camera_near_Roswell",
104
+
time = "2025-06-15"
105
+
)
106
+
```
90
107
91
-
Pass POSIXct values (in UTC) to `after` and `before` to fetch images from a specific window:
108
+
A two-element vector sets a closed window. Use `NA` for an open bound:
92
109
93
-
```{rdate-filter}
110
+
```{rtime-window}
94
111
list_images(
95
-
cam_id,
96
-
after = as.POSIXct("2025-06-01 00:00:00", tz = "UTC"),
97
-
before = as.POSIXct("2025-06-02 00:00:00", tz = "UTC")
112
+
"NM_Pecos_Web_Camera_near_Roswell",
113
+
time = c("2025-06-01", "2025-06-03")
98
114
)
99
115
```
100
116
101
-
##Building image URLs
117
+
### Chronological order
102
118
103
-
`build_image_url()` combines the camera's base S3 directory with the filenames returned by `list_images()`:
119
+
By default results are newest-first. Pass `recent = FALSE` to flip the order—useful when you want frames in chronological order before building an animation:
-`"small"` (default) — ~720 px wide, suitable for monitoring dashboards
113
-
-`"overlay"` — full-size overlay image with gage-reading annotation
114
-
-`"thumb"` — thumbnail ~200 px tall
127
+
The `limit` argument controls the API page size (1–50,000). When the camera has more images than `limit`, `list_images()` paginates automatically using a timestamp cursor and returns all matching records in a single tibble.
115
128
116
129
## Downloading images
117
130
118
-
`download_images()`wraps the steps above into a single call: it finds the camera, lists images, builds URLs, and saves the files to a local directory.
131
+
`download_images()`lists the images for a camera and saves them to a local directory in one call. You must create the destination directory beforehand:
119
132
120
-
```{r download}
121
-
dest <- tempdir()
133
+
```{r download-basic}
134
+
dest <- file.path(tempdir(), "roswell")
135
+
dir.create(dest, showWarnings = FALSE)
122
136
123
137
paths <- download_images(
124
-
cam_id = cam_id,
138
+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
125
139
dest_dir = dest,
126
140
size = "small",
127
-
limit = 5
141
+
limit = 10
128
142
)
143
+
```
144
+
145
+
`paths` is a character vector of local file paths returned invisibly. Failed downloads are represented as `NA`.
|`"overlay"`| Full resolution | Gage-reading annotation visible |
153
+
|`"thumb"`|~200 px tall | Quick visual overview |
154
+
155
+
### Time filtering
129
156
130
-
paths
157
+
Pass the same `time` argument as `list_images()` to restrict which images are downloaded:
158
+
159
+
```{r download-window}
160
+
paths <- download_images(
161
+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
162
+
dest_dir = dest,
163
+
size = "small",
164
+
time = c("2025-06-10", "2025-06-12")
165
+
)
131
166
```
132
167
133
-
Already-downloaded files are skipped by default (`overwrite = FALSE`), making it easy to resume a partially completed download. Pass `overwrite = TRUE` to force re-download.
168
+
### Resuming partial downloads
169
+
170
+
`download_images()` skips files that already exist in `dest_dir` when `overwrite = FALSE` (the default). If a download is interrupted, simply re-run the same call and only the missing files will be fetched.
171
+
172
+
## Making a GIF
134
173
135
-
## Timelapse videos
174
+
`make_gif()` fetches images and encodes them into an animated GIF. It requires the `gifski` package.
136
175
137
-
Many USGS cameras produce a daily timelapse MP4 stitched from images collected throughout the day. `get_timelapse_url()` returns the URL to that file:
176
+
The simplest call streams images directly from NIMS—no separate download step needed:
177
+
178
+
```{r gif-direct}
179
+
make_gif(
180
+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
181
+
time = c("2025-06-10", "2025-06-12"),
182
+
fps = 2,
183
+
output = "roswell.gif"
184
+
)
185
+
```
186
+
187
+
If you already downloaded images with `download_images()`, point to that directory with `dir` to skip re-downloading:
188
+
189
+
```{r gif-from-dir}
190
+
make_gif(
191
+
dir = dest,
192
+
fps = 2,
193
+
output = "roswell.gif"
194
+
)
195
+
```
138
196
139
-
```{r timelapse}
140
-
url <- get_timelapse_url(cam_id)
141
-
url
197
+
### One frame per day
198
+
199
+
For a range spanning many days the result can be hundreds of frames. Pass `one_per_day = TRUE` to reduce the animation to a single frame per calendar day, selecting the image whose capture time is closest to local noon:
200
+
201
+
```{r gif-one-per-day}
202
+
make_gif(
203
+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
204
+
time = c("2025-05-01", "2025-06-30"),
205
+
fps = 4,
206
+
one_per_day = TRUE,
207
+
output = "roswell_monthly.gif"
208
+
)
209
+
```
210
+
211
+
When `output` is not specified the file is written to `"<cam_id>.gif"` in the working directory.
212
+
213
+
## Making a video
214
+
215
+
`make_video()` produces an MP4 instead of a GIF. It requires the `av` package and accepts the same arguments as `make_gif()`:
216
+
217
+
```{r video-direct}
218
+
make_video(
219
+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
220
+
time = c("2025-06-10", "2025-06-12"),
221
+
fps = 4,
222
+
output = "roswell.mp4"
223
+
)
224
+
```
225
+
226
+
Build from an already-downloaded directory:
227
+
228
+
```{r video-from-dir}
229
+
make_video(
230
+
dir = dest,
231
+
fps = 4,
232
+
output = "roswell.mp4"
233
+
)
142
234
```
143
235
144
-
You can open the URL directly in a browser or pass it to a video tool. A warning is emitted when `TL_enabled` is `FALSE` for the camera.
236
+
MP4 files are substantially smaller than equivalent GIFs at the same resolution and frame count, making them preferable for longer time ranges or larger image sizes. GIFs are more portable for sharing in contexts that don't support video embedding.
145
237
146
238
## Next steps
147
239
148
-
-See `vignette("pecos-river")`for a full monitoring workflow combining **flowcam**with streamflow data from **dataRetrieval**.
149
-
-Use `find_gage_cameras()` to retrieve camera metadata enriched with NWIS site attributes (drainage area, elevation, hydrologic unit, etc.).
240
+
-`vignette("pecos-river")`shows how to use `find_gage_cameras()` to enrich camera records with NWIS site metadata and compare two cameras on the same river reach.
241
+
-The full function reference is at <https://connorb.github.io/flowcam/reference/>.
0 commit comments