Thanks to @PySir I got it working!
You were right. You cannot "Upload & Publish" in one step, the video needs to be first uploaded and then you can 'create a video object' on your channel, then publish it. After uploading a video you can then create the object and publish in one step and thats where I was getting confused as the docs say to 'upload & publish'
Anyways, Here's what I used:
app.post('/api/dailymotion/upload', async (req, res) => {
const localVideoDirectory = path.join(__dirname, 'videos');
try {
const videos = fs.readdirSync(localVideoDirectory)
.filter(file => file.endsWith('.mp4') || file.endsWith('.mkv') || file.endsWith('.avi'))
.map(file => ({
name: file,
path: path.join(localVideoDirectory, file),
normalizedName: file.replace(/\.[^/.]+$/, '').toLowerCase(),
}));
if (!videos.length) {
return res.status(400).send('No video files found in the local directory.');
}
console.log('[📂] Found Local Videos:', videos);
const token = await getAccessToken();
const existingVideosResponse = await axios.get(`${DAILY_API_BASE}/me/videos`, {
params: { fields: 'title', access_token: token },
});
const existingVideoTitles = existingVideosResponse.data.list.map(video =>
video.title.toLowerCase().trim()
);
console.log('[📂] Existing Dailymotion Videos:', existingVideoTitles);
const videosToUpload = videos.filter(video =>
!existingVideoTitles.includes(video.normalizedName)
);
console.log('[📂] Videos to Upload:', videosToUpload);
if (!videosToUpload.length) {
return res.status(200).send('All videos are already uploaded.\n');
}
const uploadResults = await Promise.all(videosToUpload.map(async (video) => {
try {
console.log(`[📂] Preparing to upload video: ${video.name}`);
const uploadUrlResponse = await axios.get(`${DAILY_API_BASE}/file/upload`, {
params: { access_token: token },
});
const uploadUrl = uploadUrlResponse.data.upload_url;
console.log('[🌐] Upload URL:', uploadUrl);
const videoData = fs.readFileSync(video.path);
const form = new FormData();
form.append('file', videoData, video.name);
const uploadResponse = await axios.post(uploadUrl, form, {
headers: { ...form.getHeaders() },
maxContentLength: Infinity,
maxBodyLength: Infinity,
});
console.log('[✅] Video Uploaded:', uploadResponse.data);
const videoUrl = uploadResponse.data.url;
const videoName = uploadResponse.data.name;
console.warn('[🌐] Video URL for Publishing:', videoUrl);
console.warn('[🌐] Video Name for Publishing:', videoName);
const publishResponse = await axios.post(
`${DAILY_API_BASE}/me/videos`,
{
url: videoUrl,
title: videoName,
channel: 'music',
published: 'true',
is_created_for_kids: 'false',
},
{
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
}
);
console.log('[✅] Video Published:', publishResponse.data);
return publishResponse.data;
} catch (error) {
console.error(`[❌] Error processing video (${video.name}):`, error.response?.data || error.message);
return { error: error.message, video: video.name };
}
}));
res.json(uploadResults);
} catch (error) {
console.error('[❌] Error in upload endpoint:', error.message);
res.status(500).send('Error uploading videos.');
}
});
I need to refactor some things now, making it more comprehensive and fault tolerant and point it back to the cloud instance for finding files automatically and finish some styling. Other than that the core logic is there now and I am able to scan for and upload videos programatically! Thank you very much for your patience @PySir