فيديوهات شرح متحركة بتعليق صوتي باستخدام ToRun MCP وRemotion
آخر تحديث: 11 نوفمبر 2026
ما الذي يمكنك صنعه
يستطيع وكيل برمجة يشغّل الأوامر على حاسوبك، مثل Claude Code أو opencode أو Cursor، أن يصنع باستخدام ToRun فيديو شرح قصيرًا بتعليق صوتي. يكتب الوكيل النص، ويطلب من ToRun صور المشاهد والتعليق الصوتي والموسيقى الخلفية، ثم يصيّر الفيديو على حاسوبك باستخدام Remotion، وهي مكتبة تحوّل مكونات React إلى فيديو.
ما الذي تحتاجه
- أداة برمجة متصلة بخادم MCP من ToRun، وقادرة على تشغيل الأوامر وكتابة الملفات في مجلد: opencode أو Claude Code أو Cursor.
- Node.js 18 أو أحدث. أول عملية تصيير تنزّل المتصفح الذي يصيّر به Remotion.
- حصة خطة مدفوعة أو رصيد في المحفظة: استدعاءات API لا تستخدم الحصة المجانية أبدًا. راجع كيف تُدفع الاستدعاءات.
لـ Remotion ترخيصه الخاص: فهو مجاني للأفراد والشركات الصغيرة جدًا، أما الشركات الأكبر فتحتاج إلى ترخيص شركة. راجع remotion.dev/license قبل استخدامه في العمل.
المشروع المبدئي
أربعة ملفات. اطلب من وكيلك إنشاءها في مجلد فارغ، أو انسخها بنفسك، ثم شغّل npm install هناك. توضع الملفات المُنشأة في مجلد public بجوار package.json.
package.json:
{
"name": "motion-explainer",
"private": true,
"scripts": {
"studio": "remotion studio src/index.ts",
"render": "remotion render src/index.ts Explainer out/explainer.mp4"
},
"dependencies": {
"@remotion/cli": "4.0.539",
"react": "18.3.1",
"react-dom": "18.3.1",
"remotion": "4.0.539"
}
}
يحتوي video.json على الفيديو كله. لكل مشهد caption يُعرض على الشاشة، ونص التعليق الصوتي say، وprompt الصورة، وأسماء ملفي صورته وتعليقه الصوتي، ومدته بالثواني في seconds:
{
"width": 1920,
"height": 1080,
"fps": 30,
"music": { "file": "music.mp3", "volume": 0.12 },
"scenes": [
{
"caption": "Every team has a backlog.",
"say": "Every team has a backlog, and it only grows.",
"prompt": "flat illustration of a wall covered in sticky notes, soft morning light, no text",
"image": "scene-1.png",
"narration": "scene-1.mp3",
"seconds": 5.5
},
{
"caption": "Sort it by what users feel.",
"say": "Sort it by what your users feel, not by what is loudest.",
"prompt": "flat illustration of hands arranging cards into three columns on a desk, no text",
"image": "scene-2.png",
"narration": "scene-2.mp3",
"seconds": 6
},
{
"caption": "Ship the top one this week.",
"say": "Then ship the top one this week.",
"prompt": "flat illustration of a small paper boat leaving a harbour at sunrise, no text",
"image": "scene-3.png",
"narration": "scene-3.mp3",
"seconds": 5
}
]
}
src/index.ts:
import {registerRoot} from 'remotion';
import {Root} from './Root';
registerRoot(Root);
يشغّل src/Root.tsx المشاهد واحدًا تلو الآخر. تقترب كل صورة ببطء، ويرتفع التعليق النصي إلى مكانه، ويبدأ التعليق الصوتي للمشهد معه، وتعزف الموسيقى بهدوء تحت الفيديو كله:
import React from 'react';
import {AbsoluteFill, Composition, Html5Audio, Img, interpolate, Series, staticFile, useCurrentFrame} from 'remotion';
import data from '../video.json';
// "say" and "prompt" are the script: the narration text and the image prompt. Rendering reads the rest.
type Scene = {image: string; narration?: string; seconds: number; caption?: string; say?: string; prompt?: string};
type Video = {width: number; height: number; fps: number; music?: {file: string; volume: number}; scenes: Scene[]};
const video = data as Video;
const clamp = {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'} as const;
const framesOf = (scene: Scene) => Math.round(scene.seconds * video.fps);
// One scene: the image slowly zooms in, the caption rises in, the narration plays from the scene's start.
const SceneView: React.FC<{scene: Scene; frames: number}> = ({scene, frames}) => {
const frame = useCurrentFrame();
const fade = interpolate(frame, [0, 10, frames - 10, frames], [0, 1, 1, 0], clamp);
const zoom = interpolate(frame, [0, frames], [1, 1.08]);
const rise = interpolate(frame, [8, 26], [40, 0], clamp);
return (
<AbsoluteFill style={{backgroundColor: 'black', opacity: fade}}>
<Img src={staticFile(scene.image)} style={{width: '100%', height: '100%', objectFit: 'cover', transform: `scale(${zoom})`}} />
{scene.caption ? (
<div
style={{
position: 'absolute', left: '6%', right: '6%', bottom: '8%', transform: `translateY(${rise}px)`,
color: 'white', fontFamily: 'Arial, sans-serif', fontSize: video.height / 18, fontWeight: 700,
textShadow: '0 2px 16px rgba(0,0,0,0.7)',
}}
>
{scene.caption}
</div>
) : null}
{scene.narration ? <Html5Audio src={staticFile(scene.narration)} /> : null}
</AbsoluteFill>
);
};
const Explainer: React.FC = () => (
<AbsoluteFill style={{backgroundColor: 'black'}}>
<Series>
{video.scenes.map((scene, i) => (
<Series.Sequence key={i} durationInFrames={framesOf(scene)}>
<SceneView scene={scene} frames={framesOf(scene)} />
</Series.Sequence>
))}
</Series>
{video.music ? <Html5Audio src={staticFile(video.music.file)} volume={video.music.volume} loop /> : null}
</AbsoluteFill>
);
export const Root: React.FC = () => (
<Composition
id="Explainer"
component={Explainer}
width={video.width}
height={video.height}
fps={video.fps}
durationInFrames={video.scenes.reduce((sum, scene) => sum + framesOf(scene), 0)}
/>
);
كيف يصنع الوكيل الفيديو
النص. يكتب الوكيل المشاهد في
video.json: فكرة واحدة لكل مشهد، وتعليق نصي من بضع كلمات، وجملة أو جملتان للقول. اطلب منه أن يعرض عليك النص قبل أن ينشئ أي شيء.الرصيد. يستدعي
account_balanceليعرف ما يمكن للحساب إنفاقه. هذا الاستدعاء مجاني.الصور. لكل مشهد يستدعي
image_generateمعpromptالمشهد وsizeبقيمة1792x1024، ويحفظ الصورة باسمpublic/scene-1.pngوpublic/scene-2.pngوهكذا. إذا لم تكن الصورة جاهزة خلال مدة الانتظار، تعيد الأداة معرّف مهمة، ويسأل الوكيلjob_statusحتى تجهز الصورة.التعليق الصوتي. لكل مشهد يستدعي
tts_generateمع نصsayللمشهد وصوت، مثلnova، ويحفظ الصوت باسمpublic/scene-1.mp3وهكذا.التوقيت. يضبط
secondsلكل مشهد على مدة تعليقه الصوتي مضافًا إليها نحو نصف ثانية. تعيدtts_generateهذه المدة فيduration_seconds، مقيسة من الملف الصوتي. إذا تضمّن الرد أيضًاduration_estimated: true، فقد أمكن تقدير المدة من النص فقط، لذا يقيس الوكيل الملف. للتحقق من ملف بنفسك:npx remotion ffprobe -v error -show_entries format=duration -of csv=p=0 public/scene-1.mp3الموسيقى (اختياري). يستدعي
music_generateمع موجّه مثل «calm instrumental background, soft piano»، وwith_vocalsبقيمةfalse، وduration_secondsقريبة من مدة الفيديو. تعيد الأداة معرّف مهمة؛ ويسأل الوكيلjob_statusحتى يجهز المقطع، ثم يحفظه باسمpublic/music.mp3. إذا لم ترغب في الموسيقى، فاحذف سطرmusicمنvideo.json.المعاينة والتصيير. يفتح
npm run studioمعاينة في متصفحك. ويكتبnpm run renderالملفout/explainer.mp4.
كل رابط ملف تعيده أداة يُنزَّل دون تسجيل الدخول. احتفظ بالرابط كاملًا، بما في ذلك الجزء الذي يلي علامة الاستفهام:
curl -L -o public/scene-1.png "<the image link>"
اطلب من وكيلك
اصنع فيديو شرح مدته 30 ثانية عن طريقة عمل المزامنة في تطبيقنا، باستخدام مشروع Remotion المبدئي من torun.ai/docs/mcp-motion-explainers. أربعة مشاهد. اعرض عليّ النص في video.json أولًا. ثم أنشئ صورة واحدة لكل مشهد بلا نص فيها، وسجّل تعليقًا صوتيًا لكل مشهد بالصوت nova، وأضف موسيقى آلية هادئة، واضبط مدة كل مشهد على تعليقه الصوتي، ثم صيّر الفيديو.
لفيديو عمودي، اطلب width بقيمة 1080 وheight بقيمة 1920 في video.json، وصورًا بقيمة size 1024x1792.
كم يكلّف ذلك
image_generateوtts_generateوmusic_generateاستدعاءات مدفوعة، تُحتسب بوحدات Runs بالأسعار نفسها في التطبيق. الفيديو المكوّن من أربعة مشاهد مع موسيقى يعني أربع صور وأربعة تعليقات صوتية ومقطعًا موسيقيًا واحدًا.account_balanceوjob_statusمجانيان.- يجري التصيير على حاسوبك. تغيير التعليقات النصية أو التوقيت أو الحركة ثم التصيير مجددًا لا يكلّف شيئًا على ToRun؛ أما إنشاء صورة أو تعليق صوتي مجددًا فهو استدعاء مدفوع جديد.
- عندما تكون تكلفة عملية إنشاء واحدة أعلى من حدّ المفتاح، تجيب الأداة بالسعر أولًا، ويسألك وكيلك قبل أن ينفّذ الاستدعاء.
- كل ما ينشئه الوكيل يُحفظ أيضًا في مكتبتك على ToRun.
نصائح
- اطلب صورًا بلا نص فيها. فالتعليق النصي يحمل الكلمات، ونماذج الصور كثيرًا ما تخطئ في كتابة النص.
- اقصر كل مشهد على فكرة واحدة وجملة أو جملتين من التعليق الصوتي.
- اختر صوتًا واحدًا والتزم به طوال الفيديو.
- أبقِ مستوى صوت الموسيقى بين
0.1و0.15، كي يبقى التعليق الصوتي واضحًا.