Chuyển đổi bản thuyết trình PowerPoint sang video trong Python

Tổng quan

Chuyển đổi một bản thuyết trình PowerPoint hoặc OpenDocument sang video cho phép người xem xem nội dung trong một trình phát video mà không cần mở ứng dụng thuyết trình. Aspose.Slides for Python via Java chuyển đổi các hoạt ảnh và chuyển tiếp của bản thuyết trình thành các khung hình ảnh. Một bộ mã hoá riêng, chẳng hạn FFmpeg, sẽ ghép các khung này lại thành một tệp video.

Chuyển đổi PowerPoint sang Video

Quá trình chuyển đổi có hai giai đoạn: tạo các khung PNG ở tốc độ khung được chọn, sau đó mã hoá chuỗi hình ảnh thành MP4. Sử dụng cùng một tốc độ khung ở cả hai giai đoạn để giữ nguyên thời gian hoạt ảnh.

Trước khi chạy ví dụ:

  1. Cài đặt Aspose.Slides for Python via Java.
  2. Tải xuống FFmpeg và đưa tệp thực thi của nó vào PATH. Ví dụ sử dụng bản dựng có bộ mã hoá libx264.
  3. Chạy đoạn mã Python sau trong một thư mục có quyền ghi.

Ví dụ tạo một hình dạng cười với hoạt ảnh nhập và xuất, tạo khung ở 30 FPS và gọi FFmpeg để tạo output.mp4. Thư mục khung mới ngăn các khung từ các lần chạy trước bị đưa vào 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}.")

Để chuyển đổi một tệp hiện có, khởi tạo Presentation bằng đường dẫn của nó và bỏ qua các câu lệnh tạo hình dạng và tạo hoạt ảnh.

Lệnh FFmpeg đọc một image sequence được đánh số, bổ sung các kích thước lẻ thành chẵn và ghi video H.264 với định dạng pixel yuv420p. Tùy chọn -n ngăn ghi đè lên tệp đầu ra đã tồn tại. Các tệp PNG được tạo sẽ vẫn còn trong thư mục khung; hãy xóa chúng khi không còn cần thiết.

Hiệu ứng Video

Hoạt ảnh điều khiển cách các đối tượng trên slide xuất hiện, di chuyển hoặc biến mất. Chuyển tiếp điều khiển sự thay đổi giữa các slide. Thêm các hiệu ứng này trước khi tạo khung video.

Xem PowerPoint Animation, Shape Animation, Shape Effects, và Slide Transitions.

Thêm Chuyển tiếp Slide

Ví dụ tự chứa sau tạo một bản thuyết trình với hai slide. Slide thứ hai có nền màu hồng tươi và chuyển tiếp kiểu đẩy. Lưu bản thuyết trình, sau đó dùng nó làm đầu vào cho ví dụ tạo khung ở trên.

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()

Hoạt ảnh Đoạn Văn

Văn bản có thể xuất hiện từng đoạn một. Ví dụ này tạo ba đoạn văn với hiệu ứng nhập mờ dần tuần tự, mỗi đoạn trì hoãn một giây sau hiệu ứng trước. Sử dụng tệp paragraphs.pptx đã lưu làm đầu vào cho ví dụ chuyển đổi 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()

Các lớp Chuyển đổi Video

PresentationAnimationsGenerator tạo các sự kiện hoạt ảnh cho các slide. Khi khởi tạo từ một bản thuyết trình, nó sử dụng kích thước slide của bản thuyết trình để xác định kích thước khung. Sử dụng setDefaultDelay để cấu hình độ trễ mặc định tính bằng mili giây.

PresentationPlayer lấy mẫu các hoạt ảnh đã tạo ở tốc độ khung được cung cấp cho hàm khởi tạo. Đăng ký một callback Python qua JPype bằng setFrameTick, sau đó gọi run để tạo các khung. Ví dụ đầu tiên dùng bộ đếm bắt đầu từ 0 riêng của nó để tên tệp khớp với chuỗi đầu vào của FFmpeg.

Đối với các trạng thái hoạt ảnh riêng lẻ, đăng ký một callback bằng setNewAnimation. Callback nhận một trình phát hoạt ảnh có thể được đặt tại thời điểm đã chọn. Ví dụ dưới đây lưu khung đầu và cuối của mỗi hoạt ảnh đã tạo với tên tệp duy nhất:

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()

Các Hoạt ảnh và Hiệu ứng được Hỗ trợ

Các bảng sau tóm tắt mức độ hỗ trợ render được mô tả trong bài viết chuyển đổi Java. Xem trước các khung đã tạo khi bản thuyết trình sử dụng các hiệu ứng chưa được hỗ trợ.

Entrance:

Loại Hoạt ảnh Aspose.Slides PowerPoint
Appear Không
Fade
Fly In
Float In
Split
Wipe
Shape
Wheel
Random Bars
Grow & Turn Không
Zoom
Swivel
Bounce

Emphasis:

Loại Hoạt ảnh Aspose.Slides PowerPoint
Pulse Không
Color Pulse Không
Teeter
Spin
Grow/Shrink Không
Desaturate Không
Darken Không
Lighten Không
Transparency Không
Object Color Không
Complementary Color Không
Line Color Không
Fill Color Không

Exit:

Loại Hoạt ảnh Aspose.Slides PowerPoint
Disappear Không
Fade
Fly Out
Float Out
Split
Wipe
Shape
Random Bars
Shrink & Turn Không
Zoom
Swivel
Bounce

Motion Paths:

Loại Hoạt ảnh Aspose.Slides PowerPoint
Lines
Arcs
Turns
Shapes
Loops
Custom Path

Câu hỏi thường gặp

Aspose.Slides có tạo tệp MP4 trực tiếp không?

Không. Aspose.Slides tạo các khung của bản thuyết trình. Sử dụng bộ mã hoá video như FFmpeg để ghép chúng thành tệp MP4.

Tại sao video phát nhanh hoặc chậm hơn mong đợi?

Sử dụng cùng FPS cho việc tạo khung và tốc độ khung đầu vào của bộ mã hoá. Sự không khớp sẽ làm thay đổi thời lượng phát lại của chuỗi hình ảnh.

Tôi có thể chuyển đổi bản thuyết trình được bảo vệ bằng mật khẩu không?

Có. Cung cấp mật khẩu đúng khi loading the protected presentation, sau đó tạo khung từ nội dung đã tải.

Quy trình này có bảo lưu âm thanh của bản thuyết trình không?

Các ví dụ xuất các khung hình ảnh, vì vậy video tạo ra sẽ không có âm thanh. Để bao gồm âm thanh, bạn cần cung cấp một track âm thanh riêng trong quá trình mã hoá video.

Làm sao giảm việc sử dụng đĩa tạm?

Sử dụng kích thước khung nhỏ hơn hoặc FPS thấp hơn, và xóa các tệp PNG tạm sau khi mã hoá thành công. Kiểm tra chất lượng video kết quả khi giảm bất kỳ cài đặt nào.