Python에서 PowerPoint 프레젠테이션을 비디오로 변환

개요

PowerPoint 또는 OpenDocument 프레젠테이션을 비디오로 변환하면 프레젠테이션 애플리케이션을 열지 않고도 비디오 플레이어에서 내용을 시청할 수 있습니다. Aspose.Slides for Python via Java은 프레젠테이션 애니메이션 및 전환을 이미지 프레임으로 렌더링합니다. FFmpeg과 같은 별도의 인코더가 이러한 프레임을 비디오 파일로 결합합니다.

PowerPoint를 비디오로 변환

변환은 두 단계로 진행됩니다. 선택한 프레임 속도로 PNG 프레임을 생성한 뒤 이미지 시퀀스를 MP4로 인코딩합니다. 두 단계에서 동일한 프레임 속도를 사용해야 애니메이션 타이밍이 유지됩니다.

예제를 실행하기 전에:

  1. Aspose.Slides for Python via Java를 설정합니다.
  2. FFmpeg을 다운로드하고 실행 파일을 PATH에 추가합니다. 예제에서는 libx264 인코더가 포함된 빌드를 사용합니다.
  3. 쓰기 가능한 디렉터리에서 다음 Python 코드를 실행합니다.

예제는 입장 및 퇴장 애니메이션이 있는 웃는 모양을 만들고, 30 FPS로 프레임을 렌더링한 뒤 FFmpeg을 호출해 output.mp4를 생성합니다. 새 프레임 디렉터리를 사용하면 이전 실행의 프레임이 비디오에 포함되는 것을 방지할 수 있습니다.

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}.")

기존 파일을 변환하려면 경로와 함께 Presentation을 초기화하고 모양 및 애니메이션 생성 문장을 생략하면 됩니다.

FFmpeg 명령은 번호가 매겨진 image sequence를 읽고, 홀수 차원을 짝수 값으로 패딩한 뒤 yuv420p 픽셀 포맷으로 H.264 비디오를 기록합니다. -n 옵션은 기존 출력 파일을 덮어쓰는 것을 방지합니다. 생성된 PNG 파일은 프레임 디렉터리에 남아 있으며, 더 이상 필요하지 않을 때 삭제하십시오.

비디오 효과

애니메이션은 슬라이드 개체가 나타나고, 이동하고, 사라지는 방식을 제어합니다. 전환은 슬라이드 간 전환을 제어합니다. 비디오 프레임을 생성하기 전에 이러한 효과를 추가하십시오.

PowerPoint Animation, Shape Animation, Shape Effects, 및 Slide Transitions을 참조하십시오.

슬라이드 전환 추가

다음 독립형 예제는 두 개의 슬라이드가 있는 프레젠테이션을 생성합니다. 두 번째 슬라이드에는 마젠타 배경과 푸시 전환이 적용됩니다. 프레젠테이션을 저장한 뒤 위의 프레임 생성 예제 입력으로 사용하십시오.

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

단락 애니메이션

텍스트는 단락별로 나타날 수 있습니다. 이 예제는 순차적인 페이드 입장 효과가 적용된 세 개의 단락을 만들고, 각 효과는 이전 효과 이후 1초씩 지연됩니다. 저장된 paragraphs.pptx 파일을 비디오 변환 예제의 입력으로 사용하십시오.

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

비디오 변환 클래스

PresentationAnimationsGenerator는 슬라이드에 대한 애니메이션 이벤트를 생성합니다. 프레젠테이션에서 생성하면 슬라이드 크기가 프레임에 사용됩니다. 기본 지연을 밀리초 단위로 설정하려면 setDefaultDelay를 사용하십시오.

PresentationPlayer는 생성된 애니메이션을 생성자에 전달된 프레임 속도로 샘플링합니다. JPype를 통해 setFrameTick으로 Python 콜백을 등록한 뒤, run을 호출해 프레임을 생성합니다. 첫 번째 예제는 파일 이름이 FFmpeg 입력 시퀀스와 일치하도록 자체 0 기반 카운터를 사용합니다.

개별 애니메이션 상태에 대해서는 setNewAnimation으로 콜백을 등록하십시오. 콜백은 선택한 시간에 위치시킬 수 있는 애니메이션 플레이어를 받습니다. 다음 예제는 각 생성된 애니메이션의 첫 번째와 마지막 프레임을 고유 파일 이름으로 저장합니다:

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

지원되는 애니메이션 및 효과

다음 표는 Java 변환 문서에 설명된 렌더링 지원을 요약합니다. 프레젠테이션이 지원되지 않는 효과를 사용할 경우 생성된 프레임을 미리 확인하십시오.

입장:

애니메이션 유형 Aspose.Slides PowerPoint
Appear 아니오
Fade
Fly In
Float In
Split
Wipe
Shape
Wheel
Random Bars
Grow & Turn 아니오
Zoom
Swivel
Bounce

강조:

애니메이션 유형 Aspose.Slides PowerPoint
Pulse 아니오
Color Pulse 아니오
Teeter
Spin
Grow/Shrink 아니오
Desaturate 아니오
Darken 아니오
Lighten 아니오
Transparency 아니오
Object Color 아니오
Complementary Color 아니오
Line Color 아니오
Fill Color 아니오

퇴장:

애니메이션 유형 Aspose.Slides PowerPoint
Disappear 아니오
Fade
Fly Out
Float Out
Split
Wipe
Shape
Random Bars
Shrink & Turn 아니오
Zoom
Swivel
Bounce

모션 경로:

애니메이션 유형 Aspose.Slides PowerPoint
Lines
Arcs
Turns
Shapes
Loops
Custom Path

FAQ

Aspose.Slides가 MP4 파일을 직접 생성합니까?

아니오. Aspose.Slides는 프레젠테이션 프레임을 생성합니다. FFmpeg과 같은 비디오 인코더를 사용해 프레임을 MP4 파일로 결합해야 합니다.

비디오가 예상보다 빠르거나 느리게 재생되는 이유는 무엇인가요?

프레임 생성과 인코더 입력 프레임 속도를 동일하게 사용하십시오. 속도가 일치하지 않으면 이미지 시퀀스의 재생 시간이 변합니다.

비밀번호로 보호된 프레젠테이션을 변환할 수 있나요?

예. 보호된 프레젠테이션 로드 시 올바른 비밀번호를 제공한 뒤, 로드된 콘텐츠에서 프레임을 생성하십시오.

이 워크플로우가 프레젠테이션 오디오를 보존합니까?

예제는 이미지 프레임만 내보내므로 결과 비디오는 무음입니다. 오디오를 포함하려면 비디오 인코딩 중에 별도로 오디오 트랙을 제공하십시오.

임시 디스크 사용량을 줄이는 방법은?

프레임 크기를 작게 하거나 FPS를 낮추고, 인코딩이 성공하면 임시 PNG 파일을 삭제하십시오. 설정을 낮출 때 비디오 품질을 확인하십시오.