@spree/docs 0.1.165 → 0.1.167
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Media
|
|
3
3
|
sidebarTitle: "Media"
|
|
4
|
-
description: Manage product media in Spree — images,
|
|
4
|
+
description: Manage product media in Spree — images, hosted and external video, named variants, focal points, and how media is uploaded, resized, and served via the Store API.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
import { Since } from '/snippets/since.mdx';
|
|
@@ -106,6 +106,99 @@ The Store API's `media` field on a product returns its gallery — product-level
|
|
|
106
106
|
|
|
107
107
|
This dual rendering means existing storefronts keep working during the upgrade; new uploads attach to the product, and you opt into a [one-shot migration](../upgrades/5.4-to-5.5.md) to re-home legacy variant-pinned data when convenient.
|
|
108
108
|
|
|
109
|
+
### Video
|
|
110
|
+
|
|
111
|
+
A product gallery can hold video as well as images. Spree supports both ways merchants usually have it:
|
|
112
|
+
|
|
113
|
+
| `media_type` | What it is | What it needs |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| `video` | A video file you upload, served from your own storage | An uploaded file (MP4, WebM, or QuickTime) |
|
|
116
|
+
| `external_video` | A YouTube or Vimeo link | The link, in `external_video_url` |
|
|
117
|
+
|
|
118
|
+
Spree reads the link once, when it is saved, and rejects anything it cannot embed — so a broken URL is caught at the point a merchant enters it rather than in the storefront. What it derives comes back on the media object:
|
|
119
|
+
|
|
120
|
+
| Field | Description |
|
|
121
|
+
|---|---|
|
|
122
|
+
| `video_provider` | `youtube` or `vimeo` |
|
|
123
|
+
| `video_embed_url` | Player URL, ready for an `iframe` |
|
|
124
|
+
| `video_url` | The uploaded file itself, for hosted video |
|
|
125
|
+
| `poster_url` | A still frame for the video |
|
|
126
|
+
|
|
127
|
+
Because the derived fields are on the response, a storefront embeds a video without parsing links itself.
|
|
128
|
+
|
|
129
|
+
#### Adding an external video
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
```typescript Admin SDK
|
|
133
|
+
const video = await client.products.media.create('prod_86Rf07xd4z', {
|
|
134
|
+
media_type: 'external_video',
|
|
135
|
+
external_video_url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
|
136
|
+
alt: 'How it is made',
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
video.video_embed_url // https://www.youtube.com/embed/dQw4w9WgXcQ
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```bash cURL
|
|
143
|
+
curl -X POST 'https://api.mystore.com/api/v3/admin/products/prod_86Rf07xd4z/media' \
|
|
144
|
+
-H 'X-Spree-API-Key: sk_xxx' \
|
|
145
|
+
-H 'Content-Type: application/json' \
|
|
146
|
+
-d '{
|
|
147
|
+
"media_type": "external_video",
|
|
148
|
+
"external_video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
|
149
|
+
"alt": "How it is made"
|
|
150
|
+
}'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
#### Uploading a video file
|
|
155
|
+
|
|
156
|
+
A hosted video is uploaded the same way an image is, with `media_type` telling Spree what it is. Add `poster_signed_id` to give it a still frame:
|
|
157
|
+
|
|
158
|
+
```typescript Admin SDK
|
|
159
|
+
const video = await client.products.media.create('prod_86Rf07xd4z', {
|
|
160
|
+
media_type: 'video',
|
|
161
|
+
signed_id: signedVideoBlobId,
|
|
162
|
+
poster_signed_id: signedPosterBlobId,
|
|
163
|
+
alt: 'Product in use',
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
A poster can also be added or replaced later, on its own:
|
|
168
|
+
|
|
169
|
+
```typescript Admin SDK
|
|
170
|
+
await client.products.media.update('prod_86Rf07xd4z', 'media_k5nR8xLq', {
|
|
171
|
+
poster_signed_id: signedPosterBlobId,
|
|
172
|
+
})
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
> **INFO:** Spree serves an uploaded video as you uploaded it — it does not transcode. Keep files web-friendly (H.264 MP4 or WebM) so they play everywhere, and prefer an external video for long footage so the provider handles streaming.
|
|
176
|
+
|
|
177
|
+
#### Posters
|
|
178
|
+
|
|
179
|
+
A video has no image of its own, so its sized URLs (`small_url`, `large_url`, and the rest) resolve to its **poster** — the still shown before the video plays. A gallery that only knows how to draw an image still renders the right picture, and can play the video when the shopper asks for it.
|
|
180
|
+
|
|
181
|
+
Where the poster comes from, in order:
|
|
182
|
+
|
|
183
|
+
1. **The one the merchant uploaded** — `poster_signed_id` on write, editable in the dashboard's media editor.
|
|
184
|
+
2. **The provider's own still**, for a YouTube link.
|
|
185
|
+
3. **Nothing**, for a Vimeo link or an uploaded file with no poster — the tile falls back to a placeholder.
|
|
186
|
+
|
|
187
|
+
Spree does not extract a frame from an uploaded video, so give hosted video and Vimeo links a poster if you want them to show a still.
|
|
188
|
+
|
|
189
|
+
### Focal Point
|
|
190
|
+
|
|
191
|
+
`focal_point_x` and `focal_point_y` mark the part of an image that must stay in frame when a storefront crops it to a different shape. Both are fractions between 0 and 1, measured from the top left, so `{ x: 0.5, y: 0.5 }` is dead centre — which is also what a storefront should assume when they are null.
|
|
192
|
+
|
|
193
|
+
```typescript Admin SDK
|
|
194
|
+
await client.products.media.update('prod_86Rf07xd4z', 'media_k5nR8xLq', {
|
|
195
|
+
focal_point_x: 0.25,
|
|
196
|
+
focal_point_y: 0.4,
|
|
197
|
+
})
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Spree stores the focal point and serves it; the cropping itself is the storefront's decision, since only it knows the shape it needs.
|
|
201
|
+
|
|
109
202
|
### Named Variant Sizes
|
|
110
203
|
|
|
111
204
|
When an image is uploaded, Spree automatically generates optimized versions in the background:
|
|
@@ -226,6 +319,10 @@ curl 'https://api.mystore.com/api/v3/store/products/spree-tote?expand=media,vari
|
|
|
226
319
|
| `focal_point_x` | number \| null | Horizontal focal point (0.0–1.0) |
|
|
227
320
|
| `focal_point_y` | number \| null | Vertical focal point (0.0–1.0) |
|
|
228
321
|
| `external_video_url` | string \| null | External video URL (YouTube/Vimeo) |
|
|
322
|
+
| `video_provider` | string \| null | `youtube` or `vimeo`, derived from the link |
|
|
323
|
+
| `video_embed_url` | string \| null | Embeddable player URL, derived from the link |
|
|
324
|
+
| `video_url` | string \| null | Uploaded video file URL |
|
|
325
|
+
| `poster_url` | string \| null | Still frame for a video |
|
|
229
326
|
| `original_url` | string \| null | Full-size image URL (inline disposition) |
|
|
230
327
|
| `mini_url` ... `xlarge_url` | string \| null | Named variant URLs |
|
|
231
328
|
| `download_url` | string \| null | Same blob as `original_url` but with `Content-Disposition: attachment`. Admin API only. |
|
|
@@ -255,6 +352,7 @@ Spree supports two storage service types:
|
|
|
255
352
|
- **Always provide alt text** for accessibility and SEO
|
|
256
353
|
- **Use named variant sizes** (`mini`, `small`, `medium`, `large`, `xlarge`) for optimal performance
|
|
257
354
|
- **Use a CDN** in production for faster delivery
|
|
355
|
+
- **Give every video a poster** so a gallery has something to show before playback
|
|
258
356
|
|
|
259
357
|
## Related Documentation
|
|
260
358
|
|