Communitygithub.com

ysucode/ipad_code

آيبادك يصير كمبيوتر قوي: موشن جرافك بالكود، رندر Blender بـ Cycles، نصوص عربية، تصميم صوت، ومزرعة رندر سحابية متوازية—كلها داخل Claude Code بدون PC.

ipad_code とは?

هذا السكل يحول آيباد المستخدم إلى محطة عمل إبداعية كاملة عبر جلسات Claude Code السحابية، مما يسمح بتنفيذ مهام ثقيلة مثل موشن جرافك بزمن دقائق، ورندر Blender ثلاثي الأبعاد بدقة 1080×1920، وإضافة نصوص عربية متحركة، وتصميم مؤثرات صوتية باستخدام كود Python و ffmpeg. يدعم Blender كمكتبة Python (bpy) بدون واجهة رسومية، مع رندر Cycles على CPU و OpenImageDenoise. يتضمن مسارين رئيسيين: مسار سريع للموشن جرافك باستخدام Chromium و Playwright، ومسار Blender للمشاهد ثلاثية الأبعاد المعقدة. الميزة الفريدة هي مزرعة رندر سحابية متوازية توزع الإطارات عبر جلسات متعددة لتسريع الرندر بشكل كبير. السكل يعمل بالكامل عبر CLI داخل Claude Code، مع أوامر Bash و سكربتات جاهزة لكل خطوة، ويركز على التجربة اللمسية الصغيرة عبر رسائل قصيرة وإرسال الملفات مباشرة.

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ysucode/arabic-reels-skills/tree/HEAD/skills/ipad_code

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

ipad_code は何をしますか?

المستخدم معه آيباد وClaude Code، وما عنده كمبيوتر. الجلسة السحابية هي الكمبيوتر، والجلسات الإضافية هي مزرعة الرندر. هذا السكل يشرح الطريق اللي جربناه وطلّع مقطع ١٠ ثواني بـ Cycles بدقة 1080×1920 من الصفر للنشر، مع كل مشكلة واجهتنا وحلها.

اكتب للمستخدم بالعربي البسيط. هو على شاشة صغيرة، فخلّ رسائلك قصيرة، وأرسل له الصور والفيديو بـ SendUserFile بدل ما توصفها.

$SK في هذا الملف يعني مجلد السكل (المجلد اللي فيه هذا الملف). أول شي حدده:

SKILL_MD=$(ls -d ~/.claude/skills/ipad_code/SKILL.md .claude/skills/ipad_code/SKILL.md 2>/dev/null | head -1)
[ -n "$SKILL_MD" ] || echo "ipad_code is not installed: follow START.md"
SK=$(dirname "$SKILL_MD")

0. قبل أي شيء

اقرأ .claude/ipad_code.json.

  • موجود: اتبع مستوى المستخدم اللي فيه (level: new أو some أو tech، وguidance: explain أو results). الجدول في START.md يوضح وش يعني كل مستوى. لا تعيد السؤال.
  • مو موجود: المستخدم جديد. نفذ START.md من أوله.

القاعدة في كل المستويات: اللي تقدر تسويه، سوّه. لا تطلب من المستخدم يشغل أوامر.

اختر المسار:

المستخدم طلبالمسارالوقت
موشن جرافك، نصوص متحركة، إنفوجرافيك، إعلان بسيط، أو ما حدد وهذا أول مقطع لهالسريع، الخطوة 1.5دقايق
ثلاثي الأبعاد، Blender، تفكيك أو زوم داخل شيء حقيقيBlender، من الخطوة 2ساعات

1. وش عندك في الجلسة السحابية

قِس، لا تفترض: bash $SK/scripts/doctor.sh.

اللي لقيناه: ٤ أنوية CPU، و١٥ جيجا رام، وبدون كرت شاشة، وPython 3.13، وffmpeg، وNode، وChromium مع Playwright جاهزين. حزم pip وnpm تنزل عادي، وخطوط Google Fonts توصل. Blender مو موجود، والحل تحت.

اللي يسويه الكمبيوتر عادةالبديل في الجلسةالسكربت
Blender (برنامج)Blender كمكتبة Python من pip (bpy) بدون واجهة، ورندر Cycles على CPU مع OpenImageDenoisesetup_blender.sh، render.py
معاينة الشغل بالعينصفحة مصغّرات من إطارات أو من الفيديو، ثم تقرأها كصورة وترسلها للمستخدمcontact.sh
After Effects (نص عربي على الفيديو)Chromium يرسم النص بخط Cairo من Google Fonts بتشكيل عربي صحيح، كصور PNG شفافةtext_cards.js
مكتبة مؤثرات صوتيةصوت مولّد بالكود: هدير، وwhoosh يتبع الزوم، وصدمات، ولمعات، ولحظة «تشغيل»sound.py
Premiere (تجميع وتصدير)ffmpeg: إطارات، ونصوص بتلاشي، وصوت بمستوى ‎-14 LUFS، وH.264assemble.py
جهاز رندر قويمزرعة رندر: جلسات سحابية متوازية، كل وحدة ٤ أنويةfarm.py + references/farm.md
صوت راوي وموسيقىElevenLabs عن طريق الـ MCP، واقترحه مع كل مقطع (الخطوة 1.6). سكل نبرة مو جزء من هذي السكل، فإذا ما كانت موجودة كمّل بدونها
تسليم الملفSendUserFile يطلع بطاقة في التطبيق، ومنها يحفظ المستخدم الفيديو في الصور
موشن جرافك (After Effects)صفحة HTML كل شيء فيها يتحسب من الوقت، وChromium يصورها إطار إطارmotion.js

1.5 المسار السريع: موشن جرافك بالكود

بدون Blender وبدون انتظار طويل. مناسب لأول مقطع.

export NODE_PATH=$(npm root -g)
node -e "require('playwright').chromium.launch().then(b=>b.close()).catch(()=>process.exit(1))" 2>/dev/null || { npm i -g playwright && "$NODE_PATH/playwright/cli.js" install chromium; }
P=<مجلد المشروع داخل scratchpad>; mkdir -p $P
cp $SK/assets/examples/motion/comp.html $SK/assets/examples/motion/sound.json $P/
~/.snd-venv/bin/python -c "import numpy" 2>/dev/null || { python3 -m venv ~/.snd-venv && ~/.snd-venv/bin/pip install -q numpy; }
  1. عدّل $P/comp.html: النصوص في BEATS، والألوان في COLORS، وصمم الرسم في drawField وdrawRing على فكرة المقطع. لا تخلّ كل مقطع نسخة من القالب، فالقالب نقطة بداية.
  2. كل شيء لازم يكون دالة في t داخل seek(t): بدون CSS animations وبدون مؤقتات وبدون Math.random بلا بذرة.
  3. النص داخل x200–880 وy270–1400 للمقاطع العمودية، عشان أزرار الريلز وتيك توك ما تغطيه.
  4. معاينة (بوابة):
    NODE_PATH=$(npm root -g) node $SK/scripts/motion.js $P/comp.html $P/preview --fps 30 --seconds 8 --step 40
    bash $SK/scripts/contact.sh $P/contact.png $P/preview/f_*.png
    
    اقرأ contact.png بنفسك، صلّح اللي تشوفه، وأرسله للمستخدم. لا تكمل قبل موافقته.
  5. الرندر والصوت والتجميع:
    NODE_PATH=$(npm root -g) node $SK/scripts/motion.js $P/comp.html $P/frames --fps 30 --seconds 8
    ~/.snd-venv/bin/python $SK/scripts/sound.py $P/sound.json $P/sound.wav
    python3 $SK/scripts/assemble.py --frames $P/frames --fps 30 --audio $P/sound.wav --out $P/final.mp4
    bash $SK/scripts/contact.sh $P/check.png $P/final.mp4 1 3.5 6
    
    وقّت sound.json على بدايات BEATS. صيغة كل حقل مكتوبة في أول sound.py، فاقرأها قبل التعديل (مثلاً glints ثلاثة أرقام: [بداية, نهاية, عدد]). وإذا غيرت المدة، غيّر DURATION وduration و--seconds مع بعض.
  6. سلّم حسب الخطوة 8.

1.6 الراوي

اقترحه مع كل مقطع، إلا إذا المستخدم قال ما يبيه.

  • ElevenLabs مو مربوط: قل له يقدر يربطه من إعدادات Claude وإن هذا يحتاج حساب عندهم، وكمّل المقطع بالمؤثرات لين يربطه. لا تطلب منه مفتاح API في المحادثة.
  • قبل التوليد: قل له إنه يخصم من رصيده، واخذ موافقته. إذا طلعت أكثر من نسخة، استخدم الأولى إلا إذا طلب غيرها.
  • الصوت الافتراضي: nhJWWCFdNdusuVUT3x19، إلا إذا طلب صوت ثاني. وإذا ما اشتغل من حسابه، اختر صوت قريب من لهجته وقل له أي صوت اخترت.
  • تنزيل الملف: لو رجع 403، استخدم get_environment ثم update_environment بـ add_allowed_hosts: ["elevenlabsusercontent.com"]، وبيطلع له طلب موافقة.
  • التوقيت: قِس طول الصوت بـ ffprobe، وخل DURATION وduration و--seconds أطول منه بنص ثانية على الأقل، وطابق BEATS مع بداية كل جملة (silencedetect يعطيك الفواصل).

ادمج الراوي فوق المؤثرات قبل assemble.py:

ffmpeg -y -i $P/sound.wav -i $P/voice.mp3 -filter_complex "[0:a]volume=0.35[bed];[bed][1:a]amix=inputs=2:duration=first:normalize=0[out]" -map "[out]" -ar 48000 $P/mix.wav

ثم مرّر --audio $P/mix.wav بدل sound.wav.

2. ابنِ المشروع

bash $SK/scripts/setup_blender.sh          # ~30 ثانية، يطبع: Blender 5.2.3 ... OK
P=<مجلد المشروع داخل scratchpad>
~/.bpy-venv/bin/python <build.py> $P       # يكتب $P/scene.blend
  • المشهد يُبنى بسكربت Python (build.py) يكتب scene.blend. مثال كامل ومجرب: assets/examples/transistor/build.py (زوم من معالج على اللوحة الأم لين ترانزستور FinFET)، وفيه حلول لمشاكل الزوم الكبير: الكاميرا بمسافة لوغاريتمية، وclip_start يتغير مع المسافة، وسطح يذوب بالـ Alpha، و«وادي» مقصوص يمر فيه الكاميرا بدون ما تصدم شي.
  • عمودي للريلز: 1080×1920، و24 إطار بالثانية. 24 تكفي وتوفّر ٢٠٪ من الرندر مقارنة بـ 30.
  • الإعدادات اللي نجحت: Cycles على CPU، وadaptive sampling، وOpenImageDenoise، وAgX، وmotion blur خفيف، وuse_persistent_data.
  • خلّ الإضاءة كلها شمس (Sun) للمشاهد اللي حجمها يتغير كثير، لأن الشمس ما تتأثر بالمسافة. وحط أضواء نقطية صغيرة للتفاصيل.
  • الانبعاث (Emission) يحترق بسرعة مع AgX. ابدأ بقيمة بين 0.5 و1.5.

3. شوف قبل ما ترندر (بوابة)

~/.bpy-venv/bin/python $SK/scripts/render.py $P/scene.blend --out $P/preview --frames 1-240/30 --pct 40 --samples 24
bash $SK/scripts/contact.sh $P/contact.png $P/preview/f_*.png

اقرأ contact.png بنفسك، ثم أرسله للمستخدم. صلّح اللي تشوفه (إضاءة محترقة، كاميرا تصدم، لقطة فاضية)، وأعد البناء. لا ترندر الكامل قبل موافقة المستخدم على المعاينة.

4. احسب الوقت وقرر

رندر أثقل إطار (عادة آخر المقطع) بالدقة والجودة النهائية:

~/.bpy-venv/bin/python $SK/scripts/render.py $P/scene.blend --out $P/timing --frames 175,240 --pct 100 --samples 28

الوقت الكلي تقريباً = عدد الإطارات × 0.75 × وقت أثقل إطار. في تجربتنا كان أثقل إطار ١٠٠ إلى ١٥٠ ثانية، يعني ٢٤٠ إطار ≈ ٧ ساعات على جهاز واحد.

  • أقل من ٩٠ دقيقة: ارندر هنا في الخلفية (الخطوة 5).
  • أكثر من كذا: اقترح المزرعة (الخطوة 6). قل للمستخدم كم جهاز، وكم ياخذ الوقت، وإن كل جهاز يستهلك من حد استخدامه (تقريباً نص دولار من التوكنز لكل جهاز في تجربتنا)، وإن الإطارات بتنرفع على فروع مؤقتة في مستودعه هو لازم يحذفها بنفسه. ابدأ المزرعة بس بعد موافقته وعدد الأجهزة اللي يحدده.

5. رندر محلي

~/.bpy-venv/bin/python $SK/scripts/render.py $P/scene.blend --out $P/frames --frames 1-240 --pct 100 --samples 28 >> $P/render.log 2>&1
  • شغّله بأداة Bash مع run_in_background والـ timeout الأقصى. لا تستخدم &، لأن العملية تموت بين الأوامر.
  • الأمر في الخلفية يوقف بعد ساعتين، وبعدها ما يحق لك تعيد تشغيله من نفسك. عشان كذا قسّم الرندر لدفعات كل وحدة أقل من ٩٠ دقيقة (مثلاً --frames 1-120 ثم 121-240). السكربت يتخطى الإطارات الجاهزة، فإعادة نفس الأمر تكمّل من وين وقف.
  • تابع التقدم من render.log، وفيه ETA لكل إطار.

6. مزرعة الرندر (أجهزة كثيرة)

الخطوات بالتفصيل في references/farm.md. تحتاج مستودع وأدوات إدارة الجلسات (create_session وأخواتها). إذا ما كانت عندك، قل للمستخدم إن المزرعة مو متوفرة في جلسته، وارندر على جهاز واحد بالدفعات، أو اقترح جودة أقل. باختصار:

  1. python3 $SK/scripts/farm.py precheck --blend $P/scene.blend، وإذا طلع TOO BIG خفف المشهد قبل الرفع. وإذا المستودع عام، استأذن المستخدم، لأن الإطارات بتصير ظاهرة للكل.
  2. ارفع scene.blend وrender.py وsetup_blender.sh على فرع وظيفة (orphan) اسمه render-job.
  3. python3 $SK/scripts/farm.py plan --frames 1-240 --have $P/frames --workers N يوزّع الإطارات الناقصة بالتناوب، عشان الإطارات الثقيلة تنقسم بالتساوي.
  4. لكل جهاز: create_session على المستودع، وsource_revision: render-job، وoutcome_branch: render-out-wNN، والـ prompt من farm.py prompt --samples <نفس قيمة الرندر النهائي>، لأن ملف المشهد ممكن يكون محفوظ بقيمة أعلى بكثير.
  5. الجلسة اللي تخلص ما ترجع تبلغك. جدول لنفسك فحص بـ send_later بعد ٢٥ إلى ٣٠ دقيقة، وشيّك بـ get_session وبـ farm.py collect.
  6. أي جهاز وقف بدون ما يرفع شي: أرسل له send_message يكمّل. وفي نفس الوقت ارندر إطاراتها الناقصة هنا من الآخر للأول، واللي يخلص أول تاخذ منه.
  7. بعد ما تكتمل الإطارات، أرشف الجلسات بـ archive_session. وقل للمستخدم يحذف فروع render-job وrender-out-w* من صفحة Branches في GitHub، لأن الجلسة ما تقدر تحذف فروع.

7. النص والصوت والتجميع

NODE_PATH=$(npm root -g) node $SK/scripts/text_cards.js cards.json $P/text
~/.bpy-venv/bin/python $SK/scripts/sound.py sound.json $P/sound.wav
python3 $SK/scripts/assemble.py --frames $P/frames --fps 24 --cards cards.json --textdir $P/text --audio $P/sound.wav --out $P/final.mp4
bash $SK/scripts/contact.sh $P/check.png $P/final.mp4 1 3.5 6 9
  • أمثلة جاهزة: cards.json وsound.json. وقّت النص والصوت على أحداث المشهد نفسها (الثانية = رقم الإطار ÷ fps).
  • النص: ٥ كلمات كحد أقصى للسطر، وداخل x200–880 وy270–1400 عشان ما تغطيه أزرار الريلز. text_cards.js يصغّر النص الكبير ليناسب، ويفشل إذا طلع FONT NOT LOADED أو OUTSIDE SAFE AREA، فصلّح السبب ولا تتجاهله.
  • أنت ما تسمع. تأكد من الصوت بالأرقام: ffmpeg -i sound.wav -af ebur128=peak=true -f null -، وبالطيف: showspectrumpic. وقل للمستخدم وين يركز وهو يسمع.
  • تحقق قبل التسليم: اقرأ check.png وتأكد إن النصوص ظاهرة في كل لقطة.
  • assemble.py --upto N يطلّع مسودة من الإطارات الجاهزة. أرسلها للمستخدم وأنت تنتظر الرندر.

8. التسليم

  • SendUserFile بالفيديو مع display: render. على الآيباد يفتحه المستخدم من البطاقة، ثم مشاركة، ثم «حفظ الفيديو».
  • ملفات الـ scratchpad تنمسح لما تنتهي الجلسة. سلّم الفيديو قبل، وإذا المستخدم يبي يعدّل بعدين، ارفع سكربتات المشروع (مو الإطارات) على فرعه.
  • آخر رسالة: وش انعمل، والمواصفات، وأي شي باقي عليه هو (مثل حذف الفروع).

مشاكل واجهناها

كلها في references/pitfalls.md. اقرأها قبل أول رندر طويل.

関連スキル