Konversi Presentasi PowerPoint ke Video dengan Python

Gambaran Umum

Mengonversi presentasi PowerPoint atau OpenDocument ke video memungkinkan penonton menonton kontennya di pemutar video tanpa membuka aplikasi presentasi. Aspose.Slides for Python via Java merender animasi dan transisi presentasi menjadi frame gambar. Encoder terpisah, seperti FFmpeg, menggabungkan frame tersebut menjadi file video.

Konversi PowerPoint ke Video

Konversi memiliki dua tahap: menghasilkan frame PNG pada frame rate yang dipilih, kemudian mengenkode urutan gambar menjadi MP4. Gunakan frame rate yang sama pada kedua tahap untuk mempertahankan timing animasi.

Sebelum menjalankan contoh:

  1. Siapkan Aspose.Slides for Python via Java.
  2. Unduh FFmpeg dan pastikan executable‑nya tersedia di PATH. Contoh menggunakan build dengan encoder libx264.
  3. Jalankan kode Python berikut di direktori yang dapat ditulisi.

Contoh ini membuat bentuk tersenyum dengan animasi masuk dan keluar, merender frame pada 30 FPS, dan memanggil FFmpeg untuk membuat output.mp4. Direktori frame baru mencegah frame dari run sebelumnya termasuk dalam video.

import shutil
import subprocess
import tempfile
from pathlib import Path

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import EffectPresetClassType, EffectSubtype, EffectTriggerType, EffectType, ImageFormat, Presentation, PresentationAnimationsGenerator, PresentationPlayer, ShapeType

fps = 30
frames_directory = Path(tempfile.mkdtemp(prefix="video_frames_", dir="."))
frame_count = 0

def save_frame(sender, arguments):
    global frame_count
    frame_path = frames_directory / f"frame_{frame_count:06d}.png"
    frame = arguments.getFrame()
    try:
        frame.save(str(frame_path), ImageFormat.Png)
    finally:
        frame.dispose()
    frame_count += 1

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)
    smile = slide.getShapes().addAutoShape(ShapeType.SmileyFace, 110, 20, 500, 500)
    sequence = slide.getTimeline().getMainSequence()
    entrance = sequence.addEffect(smile, EffectType.Fly, EffectSubtype.TopLeft, EffectTriggerType.AfterPrevious)
    entrance.getTiming().setDuration(2.0)
    exit_effect = sequence.addEffect(smile, EffectType.Fly, EffectSubtype.BottomRight, EffectTriggerType.AfterPrevious)
    exit_effect.setPresetClassType(EffectPresetClassType.Exit)
    exit_effect.getTiming().setDuration(2.0)

    generator = PresentationAnimationsGenerator(presentation)
    try:
        player = PresentationPlayer(generator, fps)
        try:
            callback = jpype.JProxy("com.aspose.slides.PresentationPlayer$FrameTick", dict(invoke=save_frame))
            player.setFrameTick(callback)
            generator.run(presentation.getSlides())
        finally:
            player.dispose()
    finally:
        generator.dispose()
finally:
    presentation.dispose()

ffmpeg = shutil.which("ffmpeg")
if frame_count == 0:
    print("No frames were generated.")
elif ffmpeg is None:
    print(f"FFmpeg was not found on PATH. PNG frames are available in {frames_directory}.")
else:
    input_pattern = str(frames_directory / "frame_%06d.png")
    command = [ffmpeg, "-n", "-framerate", str(fps), "-start_number", "0", "-i", input_pattern, "-vf", "pad=ceil(iw/2)*2:ceil(ih/2)*2", "-c:v", "libx264", "-pix_fmt", "yuv420p", "output.mp4"]
    result = subprocess.run(command, check=False)
    if result.returncode == 0:
        print("Saved output.mp4")
    else:
        print(f"FFmpeg failed with exit code {result.returncode}. Frames are available in {frames_directory}.")

Untuk mengonversi file yang ada, inisialisasi Presentation dengan path‑nya dan hilangkan pernyataan pembuatan shape serta animasi.

Perintah FFmpeg membaca image sequence yang bernomor, menambahkan padding pada dimensi ganjil menjadi nilai genap, dan menulis video H.264 dengan format pixel yuv420p. Opsi -n mencegah penimpaan file output yang sudah ada. File PNG yang dihasilkan tetap berada di direktori frame; hapus file tersebut ketika tidak lagi dibutuhkan.

Efek Video

Animasi mengontrol bagaimana objek slide muncul, bergerak, atau menghilang. Transisi mengontrol perubahan antar slide. Tambahkan efek ini sebelum menghasilkan frame video.

Lihat PowerPoint Animation, Shape Animation, Shape Effects, dan Slide Transitions.

Tambahkan Transisi Slide

Contoh mandiri berikut membuat presentasi dengan dua slide. Slide kedua memiliki latar belakang magenta dan transisi push. Simpan presentasi, lalu gunakan sebagai input untuk contoh pembuatan frame di atas.

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import BackgroundType, FillType, Presentation, SaveFormat, ShapeType, TransitionType

Color = jpype.JClass("java.awt.Color")

presentation = Presentation()
try:
    first_slide = presentation.getSlides().get_Item(0)
    first_slide.getShapes().addAutoShape(ShapeType.SmileyFace, 110, 20, 500, 500)
    new_slide = presentation.getSlides().addEmptySlide(first_slide.getLayoutSlide())
    new_slide.getBackground().setType(BackgroundType.OwnBackground)
    new_slide.getBackground().getFillFormat().setFillType(FillType.Solid)
    new_slide.getBackground().getFillFormat().getSolidFillColor().setColor(Color.MAGENTA)
    new_slide.getSlideShowTransition().setType(TransitionType.Push)
    presentation.save("transition.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

Animasi Paragraf

Teks dapat muncul paragraf demi paragraf. Contoh ini membuat tiga paragraf dengan efek masuk fade berurutan, masing-masing tertunda satu detik setelah efek sebelumnya. Gunakan file paragraphs.pptx yang disimpan sebagai input untuk contoh konversi video.

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import EffectSubtype, EffectTriggerType, EffectType, Paragraph, Portion, Presentation, SaveFormat, ShapeType

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)
    shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 210, 120, 300, 300)
    shape.addTextFrame("")
    paragraphs = shape.getTextFrame().getParagraphs()
    paragraphs.clear()
    sequence = slide.getTimeline().getMainSequence()
    texts = ["Aspose.Slides for Python via Java", "Convert presentation text to video", "Paragraph by paragraph"]

    for text in texts:
        paragraph = Paragraph()
        portion = Portion(text)
        paragraph.getPortions().add(portion)
        paragraphs.add(paragraph)
        effect = sequence.addEffect(paragraph, EffectType.Fade, EffectSubtype.None_, EffectTriggerType.AfterPrevious)
        effect.getTiming().setTriggerDelayTime(1.0)
        effect.getTiming().setDuration(1.0)

    presentation.save("paragraphs.pptx", SaveFormat.Pptx)
finally:
    presentation.dispose()

Kelas Konversi Video

PresentationAnimationsGenerator menghasilkan peristiwa animasi untuk slide. Membuatnya dari sebuah presentasi menggunakan ukuran slide presentasi untuk frame. Gunakan setDefaultDelay untuk mengatur delay default dalam milidetik.

PresentationPlayer mengambil sampel animasi yang dihasilkan pada frame rate yang diberikan ke konstruktornya. Daftarkan callback Python melalui JPype dengan setFrameTick, lalu panggil run untuk menghasilkan frame. Contoh pertama menggunakan penghitung berbasis nol sendiri sehingga nama file cocok dengan urutan input FFmpeg.

Untuk keadaan animasi individual, daftarkan callback dengan setNewAnimation. Callback menerima animation player yang dapat diposisikan pada waktu tertentu. Contoh berikut menyimpan frame pertama dan terakhir dari setiap animasi yang dihasilkan dengan nama file unik:

from pathlib import Path

import jpype
import asposeslides

if not jpype.isJVMStarted():
    jpype.startJVM()

from asposeslides.api import EffectSubtype, EffectTriggerType, EffectType, ImageFormat, Presentation, PresentationAnimationsGenerator, ShapeType

output_directory = Path("animation_states")
output_directory.mkdir(exist_ok=True)
animation_index = 0

def save_animation_states(animation_player):
    global animation_index
    duration = animation_player.getDuration()
    print(f"Animation {animation_index}: {duration} milliseconds")
    for label, position in [("first", 0.0), ("last", duration)]:
        animation_player.setTimePosition(position)
        frame = animation_player.getFrame()
        try:
            frame_path = output_directory / f"animation_{animation_index:04d}_{label}.png"
            frame.save(str(frame_path), ImageFormat.Png)
        finally:
            frame.dispose()
    animation_index += 1

presentation = Presentation()
try:
    slide = presentation.getSlides().get_Item(0)
    smile = slide.getShapes().addAutoShape(ShapeType.SmileyFace, 110, 20, 500, 500)
    sequence = slide.getTimeline().getMainSequence()
    effect = sequence.addEffect(smile, EffectType.Fly, EffectSubtype.TopLeft, EffectTriggerType.AfterPrevious)
    effect.getTiming().setDuration(2.0)

    generator = PresentationAnimationsGenerator(presentation)
    try:
        callback = jpype.JProxy("com.aspose.slides.PresentationAnimationsGenerator$NewAnimation", dict(invoke=save_animation_states))
        generator.setNewAnimation(callback)
        generator.run(presentation.getSlides())
    finally:
        generator.dispose()
finally:
    presentation.dispose()

Animasi dan Efek yang Didukung

Tabel berikut merangkum dukungan rendering yang dijelaskan dalam artikel konversi Java. Pratinjau frame yang dihasilkan ketika presentasi menggunakan efek yang tidak didukung.

Masuk:

Animation Type Aspose.Slides PowerPoint
Appear No Yes
Fade Yes Yes
Fly In Yes Yes
Float In Yes Yes
Split Yes Yes
Wipe Yes Yes
Shape Yes Yes
Wheel Yes Yes
Random Bars Yes Yes
Grow & Turn No Yes
Zoom Yes Yes
Swivel Yes Yes
Bounce Yes Yes

Penekanan:

Animation Type Aspose.Slides PowerPoint
Pulse No Yes
Color Pulse No Yes
Teeter Yes Yes
Spin Yes Yes
Grow/Shrink No Yes
Desaturate No Yes
Darken No Yes
Lighten No Yes
Transparency No Yes
Object Color No Yes
Complementary Color No Yes
Line Color No Yes
Fill Color No Yes

Keluar:

Animation Type Aspose.Slides PowerPoint
Disappear No Yes
Fade Yes Yes
Fly Out Yes Yes
Float Out Yes Yes
Split Yes Yes
Wipe Yes Yes
Shape Yes Yes
Random Bars Yes Yes
Shrink & Turn No Yes
Zoom Yes Yes
Swivel Yes Yes
Bounce Yes Yes

Jalur Gerakan:

Animation Type Aspose.Slides PowerPoint
Lines Yes Yes
Arcs Yes Yes
Turns Yes Yes
Shapes Yes Yes
Loops Yes Yes
Custom Path Yes Yes

Tanya Jawab

Apakah Aspose.Slides membuat file MP4 secara langsung?

Tidak. Aspose.Slides menghasilkan frame presentasi. Gunakan encoder video seperti FFmpeg untuk menggabungkannya menjadi file MP4.

Mengapa video diputar lebih cepat atau lebih lambat dari yang diharapkan?

Gunakan FPS yang sama untuk pembuatan frame dan frame rate input encoder. Ketidaksesuaian mengubah durasi pemutaran urutan gambar.

Apakah saya dapat mengonversi presentasi yang dilindungi kata sandi?

Ya. Berikan kata sandi yang benar saat loading the protected presentation, kemudian hasilkan frame dari konten yang dimuat.

Apakah alur kerja ini mempertahankan audio presentasi?

Contoh mengekspor frame gambar, sehingga video yang dihasilkan tanpa suara. Untuk menyertakan audio, tambahkan trek audio secara terpisah selama proses enkoding video.

Bagaimana saya dapat mengurangi penggunaan disk sementara?

Gunakan ukuran frame yang lebih kecil atau FPS yang lebih rendah, dan hapus file PNG sementara setelah enkoding berhasil. Periksa kualitas video yang dihasilkan saat mengurangi salah satu pengaturan tersebut.