Интеграция с Vimeo API позволяет загружать видео высокого качества, управлять настройками приватности, создавать витрины и использовать расширенные возможности платформы Vimeo для профессиональной работы с видео.
- Зарегистрируйтесь на Vimeo Developer
- Создайте новое приложение
- Получите Client ID, Client Secret и Access Token
- Настройте разрешения (scopes) для вашего приложения
- Для Production доступа пройдите верификацию приложения
// Инициализация Vimeo клиента
const vimeo = await initializeVimeo({
clientId: process.env.VIMEO_CLIENT_ID,
clientSecret: process.env.VIMEO_CLIENT_SECRET,
accessToken: process.env.VIMEO_ACCESS_TOKEN,
// Или для OAuth
redirectUri: 'timeline-studio://oauth/vimeo'
})import { createLogger } from '@/lib/tauri-logger'
const logger = createLogger('VimeoApi')
// Использование персонального токена
const vimeo = new VimeoClient({
accessToken: 'your_personal_access_token'
})
// Проверка токена
const user = await vimeo.request('/me')
logger.infoSync(`Authenticated as: ${user.name}`)// Генерация URL для авторизации
const authUrl = vimeo.buildAuthorizationEndpoint({
redirectUri: 'timeline-studio://oauth/vimeo',
state: generateSecureState(),
scopes: [
'public',
'private',
'upload',
'delete',
'video_files',
'promo_codes'
]
})
// Обмен кода на токен
const tokens = await vimeo.accessToken(authCode, redirectUri)
await saveTokens('vimeo', tokens)import { createLogger } from '@/lib/tauri-logger'
const logger = createLogger('VimeoApi')
// Простая загрузка
const upload = await vimeo.upload({
file: '/path/to/video.mp4',
name: 'Моё потрясающее видео',
description: 'Создано в Timeline Studio',
privacy: {
view: 'anybody', // 'anybody' | 'nobody' | 'password' | 'people' | 'users' | 'unlisted'
embed: 'public', // 'public' | 'private' | 'whitelist'
download: true,
add: true,
comments: 'anybody'
}
})
// Отслеживание прогресса
upload.on('progress', (progress) => {
logger.debugSync(`Загружено: ${progress.percentage}%`)
logger.debugSync(`Скорость: ${progress.bytesPerSecond} bytes/sec`)
logger.debugSync(`Осталось времени: ${progress.estimatedTimeRemaining}s`)
})
// Завершение загрузки
upload.on('complete', (video) => {
logger.infoSync(`Видео загружено: ${video.link}`)
logger.infoSync(`ID видео: ${video.resource_key}`)
})// Загрузка с расширенными настройками
const advancedUpload = await vimeo.upload({
file: '/path/to/video.mp4',
name: 'Профессиональное видео',
description: detailedDescription,
privacy: {
view: 'unlisted',
embed: 'whitelist',
download: false,
add: false,
comments: 'nobody'
},
password: 'secure_password', // Для password-protected видео
content_rating: ['safe'], // 'safe' | 'unrated' | 'nudity' | 'violence' | 'drugs' | 'language'
locale: 'ru',
license: 'by-sa', // Creative Commons лицензии
spatial: {
stereo_format: 'mono', // 'mono' | 'left-right' | 'top-bottom'
projection: 'equirectangular', // Для 360 видео
field_of_view: 90
}
})import { createLogger } from '@/lib/tauri-logger'
const logger = createLogger('VimeoApi')
// Создание resumable загрузки (Tus protocol)
const tusUpload = await vimeo.createTusUpload({
size: videoFile.size,
name: 'Large Video File',
description: 'Загрузка большого файла'
})
// Загрузка с возможностью возобновления
const uploader = vimeo.uploadWithTus(tusUpload.upload_link, {
file: videoFile,
chunkSize: 128 * 1024 * 1024, // 128MB chunks
retryDelays: [0, 1000, 3000, 5000],
onProgress: (bytesUploaded, bytesTotal) => {
updateProgressBar(bytesUploaded / bytesTotal)
},
onError: (error) => {
logger.errorSync('Ошибка загрузки:', error)
// Загрузка автоматически возобновится
}
})
// Пауза/возобновление
uploader.pause()
uploader.resume()// Обновление метаданных
await vimeo.request(`/videos/${videoId}`, {
method: 'PATCH',
body: {
name: 'Новое название',
description: 'Обновленное описание',
privacy: {
view: 'password',
password: 'new_password'
},
categories: [
'/categories/animation',
'/categories/documentary'
],
tags: ['timeline-studio', 'монтаж', '2025']
}
})
// Установка миниатюры
await vimeo.createPicture(videoId, {
time: 15.5, // Временная метка в секундах
active: true
})
// Загрузка пользовательской миниатюры
await vimeo.uploadPicture(videoId, {
file: '/path/to/thumbnail.jpg'
})import { createLogger } from '@/lib/tauri-logger'
const logger = createLogger('VimeoApi')
// Детальная информация о видео
const video = await vimeo.request(`/videos/${videoId}`, {
fields: 'uri,name,description,duration,width,height,created_time,stats,pictures,download,files'
})
logger.infoSync(`Просмотры: ${video.stats.plays}`)
logger.infoSync(`Длительность: ${video.duration}s`)
logger.infoSync(`Разрешение: ${video.width}x${video.height}`)
// Получение списка видео
const videos = await vimeo.request('/me/videos', {
page: 1,
per_page: 25,
query: 'timeline studio',
direction: 'desc',
sort: 'date',
filter: 'playable'
})// Создание папки проекта
const folder = await vimeo.request('/me/projects', {
method: 'POST',
body: {
name: 'Timeline Studio Projects',
privacy: {
view: 'anybody'
}
}
})
// Добавление видео в папку
await vimeo.request(`/me/projects/${folder.resource_key}/videos/${videoId}`, {
method: 'PUT'
})
// Создание вложенной структуры
const subFolder = await vimeo.request(`/me/projects/${folder.resource_key}/folders`, {
method: 'POST',
body: {
name: 'Tutorials'
}
})// Создание витрины
const showcase = await vimeo.request('/me/albums', {
method: 'POST',
body: {
name: 'Best of Timeline Studio',
description: 'Лучшие работы созданные в Timeline Studio',
privacy: 'anybody',
brand_color: '#FF5733',
layout: 'grid', // 'grid' | 'player' | 'list'
theme: 'dark', // 'dark' | 'light'
sort: 'manual', // 'manual' | 'date' | 'alphabetical' | 'plays' | 'likes' | 'comments' | 'duration'
hide_nav: false,
hide_upcoming: false
}
})
// Добавление видео в витрину
await vimeo.request(`/me/albums/${showcase.resource_key}/videos/${videoId}`, {
method: 'PUT',
body: {
position: 1 // Позиция в витрине
}
})// Получение кода для встраивания
const embedData = await vimeo.request(`/videos/${videoId}`, {
fields: 'embed'
})
// Настройка параметров встраивания
await vimeo.request(`/videos/${videoId}`, {
method: 'PATCH',
body: {
embed: {
title: {
name: 'show', // 'show' | 'hide'
owner: 'show',
portrait: 'show'
},
logos: {
vimeo: false,
custom: {
active: true,
link: 'https://yourdomain.com',
sticky: true
}
},
buttons: {
like: true,
watchlater: true,
share: true,
embed: false,
hd: true,
fullscreen: true,
scaling: true
},
color: '#FF5733',
volume: true,
speed: true,
pip: true // Picture-in-picture
}
}
})
// Генерация iframe
const iframe = `
<iframe
src="https://player.vimeo.com/video/${videoId}?h=${embedData.embed.html.split('h=')[1].split('"')[0]}"
width="1920"
height="1080"
frameborder="0"
allow="autoplay; fullscreen; picture-in-picture"
allowfullscreen>
</iframe>
`// Добавление доменов в whitelist
await vimeo.request(`/videos/${videoId}/privacy/domains`, {
method: 'PUT',
body: {
domain: 'yourdomain.com'
}
})
// Получение списка доменов
const domains = await vimeo.request(`/videos/${videoId}/privacy/domains`)
// Удаление домена
await vimeo.request(`/videos/${videoId}/privacy/domains/yourdomain.com`, {
method: 'DELETE'
})import { createLogger } from '@/lib/tauri-logger'
const logger = createLogger('VimeoApi')
// Общая статистика
const stats = await vimeo.request(`/videos/${videoId}/stats`)
logger.infoSync(`Всего просмотров: ${stats.plays}`)
logger.infoSync(`Уникальные зрители: ${stats.unique_viewers}`)
logger.infoSync(`Среднее время просмотра: ${stats.average_time_watched}`)
logger.infoSync(`Общее время просмотра: ${stats.total_time_watched}`)
// Детальная аналитика (требует Vimeo Pro)
const analytics = await vimeo.request(`/videos/${videoId}/analytics`, {
dimension: 'country', // 'country' | 'device_type' | 'embed_domain' | 'stream_type' | 'video'
from: '2025-01-01',
to: '2025-12-31',
sort: 'plays',
direction: 'desc'
})
// График просмотров
const timeSeriesData = await vimeo.request(`/videos/${videoId}/analytics/timeseries`, {
metric: 'plays', // 'plays' | 'loads' | 'finishes' | 'downloads' | 'unique_viewers'
interval: 'day', // 'day' | 'week' | 'month'
from: '2025-01-01',
to: '2025-12-31'
})import { createLogger } from '@/lib/tauri-logger'
const logger = createLogger('VimeoApi')
// Создание live event (требует Vimeo Premium)
const liveEvent = await vimeo.request('/me/live_events', {
method: 'POST',
body: {
title: 'Timeline Studio Live Demo',
privacy: {
view: 'anybody',
embed: 'public'
},
streaming_privacy: {
view: 'anybody'
},
schedule: {
start_time: '2025-12-25T15:00:00+00:00'
},
auto_cc: true, // Автоматические субтитры
dvr: true, // Digital Video Recorder
low_latency: true
}
})
// Получение RTMP данных
logger.infoSync(`RTMP URL: ${liveEvent.rtmp.url}`)
logger.infoSync(`Stream Key: ${liveEvent.rtmp.stream_key}`)
// Управление трансляцией
await vimeo.request(`/live_events/${liveEvent.resource_key}/activate`, {
method: 'POST'
})
await vimeo.request(`/live_events/${liveEvent.resource_key}/end`, {
method: 'POST'
})// Добавление пользователя в команду
await vimeo.request('/me/team_members', {
method: 'POST',
body: {
email: 'editor@example.com',
role: 'contributor', // 'admin' | 'contributor' | 'viewer'
folder_permission: 'edit', // 'view' | 'edit' | 'upload'
video_permission: 'edit' // 'view' | 'edit' | 'delete'
}
})
// Управление разрешениями
await vimeo.request(`/videos/${videoId}/permissions`, {
method: 'POST',
body: {
users: [
{
uri: '/users/12345',
can_edit: true,
can_delete: false,
can_view: true
}
]
}
})import { createLogger } from '@/lib/tauri-logger'
const logger = createLogger('VimeoApi')
try {
await vimeo.upload(videoData)
} catch (error) {
if (error.name === 'QUOTA_EXCEEDED') {
logger.errorSync('Превышена квота хранилища')
showUpgradePrompt()
} else if (error.name === 'INVALID_FILE') {
logger.errorSync('Неподдерживаемый формат файла')
showSupportedFormats()
} else if (error.name === 'UPLOAD_ERROR') {
logger.errorSync('Ошибка загрузки:', error.message)
// Попытка возобновления для Tus uploads
if (error.uploadUrl) {
resumeUpload(error.uploadUrl)
}
} else if (error.name === 'RATE_LIMIT') {
logger.errorSync('Превышен лимит запросов')
await delay(error.retryAfter * 1000)
}
}| Функция | Basic | Plus | Pro | Business | Premium |
|---|---|---|---|---|---|
| Хранилище/неделю | 500MB | 5GB | 20GB | Без лимита | Без лимита |
| Всего хранилище | 5GB | 250GB | 1TB | 5TB | 7TB |
| Размер файла | 500MB | 5GB | 25GB | 25GB | 25GB |
| Live streaming | ❌ | ❌ | ❌ | ✅ | ✅ |
| Аналитика | Базовая | Базовая | Расширенная | Расширенная | Расширенная |
| Команды | ❌ | ❌ | 3 члена | 10 членов | Без лимита |
- Запросы: 5000 в час (authenticated), 1000 в час (unauthenticated)
- Загрузка: Зависит от тарифного плана
- Tus chunk size: рекомендуется 128MB для больших файлов
- Используйте Tus протокол для больших файлов
- Оптимизируйте видео перед загрузкой для экономии места
- Кэшируйте данные для уменьшения API запросов
- Используйте webhooks для отслеживания событий
- Настройте домены для безопасного встраивания
- Используйте теги и категории для лучшей организации
Последнее обновление: 31 июля 2025