在 Android 上将 PowerPoint 演示文稿转换为视频

通过将 PowerPoint 演示文稿转换为视频,您可以获得

  • 可访问性提升: 所有设备(无论平台)默认都配备视频播放器,而不是演示文稿打开应用程序,因此用户更容易打开或播放视频。
  • 覆盖面更广: 通过视频,您可以触达更大的受众,并向他们提供在演示文稿中可能显得枯燥的信息。大多数调查和统计显示,人们观看和消费视频的比例高于其他内容形式,并且通常更喜欢此类内容。

Aspose.Slides 中的 PowerPoint 转视频转换

Aspose.Slides 22.11 中,我们实现了对演示文稿转视频的支持。

  • 使用 Aspose.Slides 生成一组帧(来自演示文稿幻灯片),对应特定的 FPS(每秒帧数)
  • 使用诸如 ffmpeg 的第三方工具(针对 java)根据这些帧创建视频。

将 PowerPoint 转换为视频

  1. Add this to your POM file:
   <dependency>
     <groupId>net.bramp.ffmpeg</groupId>
     <artifactId>ffmpeg</artifactId>
     <version>0.7.0</version>
   </dependency>
  1. 此处下载 ffmpeg。

  2. 运行 PowerPoint 转视频的 Java 代码。

This Java code shows you how to convert a presentation (containing a figure and two animation effects) to a video:

Presentation presentation = new Presentation();
try {
    // 添加一个笑脸形状并对其进行动画处理
    IAutoShape smile = presentation.getSlides().get_Item(0).getShapes().addAutoShape(ShapeType.SmileyFace, 110, 20, 500, 500);
    ISequence mainSequence = presentation.getSlides().get_Item(0).getTimeline().getMainSequence();
    IEffect effectIn = mainSequence.addEffect(smile, EffectType.Fly, EffectSubtype.TopLeft, EffectTriggerType.AfterPrevious);
    IEffect effectOut = mainSequence.addEffect(smile, EffectType.Fly, EffectSubtype.BottomRight, EffectTriggerType.AfterPrevious);
    effectIn.getTiming().setDuration(2f);
    effectOut.setPresetClassType(EffectPresetClassType.Exit);

    final int fps = 33;
    ArrayList<String> frames = new ArrayList<String>();

    PresentationAnimationsGenerator animationsGenerator = new PresentationAnimationsGenerator(presentation);
    try
    {
        PresentationPlayer player = new PresentationPlayer(animationsGenerator, fps);
        try {
            player.setFrameTick((sender, arguments) ->
            {
                try {
                    String frame = String.format("frame_%04d.png", sender.getFrameIndex());
                    arguments.getFrame().save(frame, ImageFormat.Png);
                    frames.add(frame);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            animationsGenerator.run(presentation.getSlides());
        } finally {
            if (player != null) player.dispose();
        }
    } finally {
        if (animationsGenerator != null) animationsGenerator.dispose();
    }

    // 配置 ffmpeg 二进制文件夹。参见此页面: https://github.com/rosenbjerg/FFMpegCore#installation
    FFmpeg ffmpeg = new FFmpeg("path/to/ffmpeg");
    FFprobe ffprobe = new FFprobe("path/to/ffprobe");

    FFmpegBuilder builder = new FFmpegBuilder()
            .addExtraArgs("-start_number", "1")
            .setInput("frame_%04d.png")
            .addOutput("output.avi")
            .setVideoFrameRate(FFmpeg.FPS_24)
            .setFormat("avi")
            .done();

    FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
    executor.createJob(builder).run();
} catch (IOException e) {
    e.printStackTrace();
}

视频效果

您可以对幻灯片中的对象应用动画,并在幻灯片之间使用切换效果。

动画和切换使幻灯片放映更具吸引力和趣味性——对视频亦是如此。让我们为前面的演示文稿的代码添加另一张幻灯片和切换效果:

// 添加一个笑脸形状并对其进行动画处理

// ...

// 添加一个新幻灯片并设置动画过渡

ISlide newSlide = presentation.getSlides().addEmptySlide(presentation.getSlides().get_Item(0).getLayoutSlide());

newSlide.getBackground().setType(BackgroundType.OwnBackground);

newSlide.getBackground().getFillFormat().setFillType(FillType.Solid);

newSlide.getBackground().getFillFormat().getSolidFillColor().setColor(Color.MAGENTA);

newSlide.getSlideShowTransition().setType(TransitionType.Push);

Aspose.Slides 也支持文本动画。因此我们对对象上的段落进行动画,使其依次出现(延迟设为一秒):

Presentation presentation = new Presentation();
try {
    // 添加文本和动画
    IAutoShape autoShape = presentation.getSlides().get_Item(0).getShapes().addAutoShape(ShapeType.Rectangle, 210, 120, 300, 300);
    Paragraph para1 = new Paragraph();
    para1.getPortions().add(new Portion("Aspose Slides for Java"));
    Paragraph para2 = new Paragraph();
    para2.getPortions().add(new Portion("convert PowerPoint Presentation with text to video"));

    Paragraph para3 = new Paragraph();
    para3.getPortions().add(new Portion("paragraph by paragraph"));
    IParagraphCollection paragraphCollection = autoShape.getTextFrame().getParagraphs();
    paragraphCollection.add(para1);
    paragraphCollection.add(para2);
    paragraphCollection.add(para3);
    paragraphCollection.add(new Paragraph());

    ISequence mainSequence = presentation.getSlides().get_Item(0).getTimeline().getMainSequence();
    IEffect effect1 = mainSequence.addEffect(para1, EffectType.Appear, EffectSubtype.None, EffectTriggerType.AfterPrevious);
    IEffect effect2 = mainSequence.addEffect(para2, EffectType.Appear, EffectSubtype.None, EffectTriggerType.AfterPrevious);
    IEffect effect3 = mainSequence.addEffect(para3, EffectType.Appear, EffectSubtype.None, EffectTriggerType.AfterPrevious);
    IEffect effect4 = mainSequence.addEffect(para3, EffectType.Appear, EffectSubtype.None, EffectTriggerType.AfterPrevious);

    effect1.getTiming().setTriggerDelayTime(1f);
    effect2.getTiming().setTriggerDelayTime(1f);
    effect3.getTiming().setTriggerDelayTime(1f);
    effect4.getTiming().setTriggerDelayTime(1f);

    final int fps = 33;
    ArrayList<String> frames = new ArrayList<String>();

    PresentationAnimationsGenerator animationsGenerator = new PresentationAnimationsGenerator(presentation);
    try
    {
        PresentationPlayer player = new PresentationPlayer(animationsGenerator, fps);
        try {
            player.setFrameTick((sender, arguments) ->
            {
                try {
                    String frame = String.format("frame_%04d.png", sender.getFrameIndex());
                    arguments.getFrame().save(frame, ImageFormat.Png);
                    frames.add(frame);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            animationsGenerator.run(presentation.getSlides());
        } finally {
            if (player != null) player.dispose();
        }
    } finally {
        if (animationsGenerator != null) animationsGenerator.dispose();
    }

    // 配置 ffmpeg 二进制文件夹。参见此页面: https://github.com/rosenbjerg/FFMpegCore#installation
    FFmpeg ffmpeg = new FFmpeg("path/to/ffmpeg");
    FFprobe ffprobe = new FFprobe("path/to/ffprobe");

    FFmpegBuilder builder = new FFmpegBuilder()
            .addExtraArgs("-start_number", "1")
            .setInput("frame_%04d.png")
            .addOutput("output.avi")
            .setVideoFrameRate(FFmpeg.FPS_24)
            .setFormat("avi")
            .done();

    FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
    executor.createJob(builder).run();
} catch (IOException e) {
    e.printStackTrace();
}

视频转换类

为了让您执行 PowerPoint 转视频的任务,Aspose.Slides 提供了 PresentationAnimationsGeneratorPresentationPlayer 类。

PresentationAnimationsGenerator 允许您通过其构造函数设置视频(稍后将创建)的帧大小。如果传入演示文稿实例,将使用 Presentation.SlideSize,并生成供 PresentationPlayer 使用的动画。

生成动画时,会为每个后续动画产生一个 NewAnimation 事件,该事件带有 IPresentationAnimationPlayer 参数。后者是表示单独动画播放器的类。

要使用 IPresentationAnimationPlayer,需要使用 Duration(动画的完整时长)属性和 SetTimePosition 方法。每个动画位置在 0 到 duration 范围内设置,然后 GetFrame 方法将返回对应该时刻动画状态的 BufferedImage:

Presentation presentation = new Presentation();
try {
    // 添加一个笑脸形状并进行动画处理
    IAutoShape smile = presentation.getSlides().get_Item(0).getShapes().addAutoShape(ShapeType.SmileyFace, 110, 20, 500, 500);
    ISequence mainSequence = presentation.getSlides().get_Item(0).getTimeline().getMainSequence();
    IEffect effectIn = mainSequence.addEffect(smile, EffectType.Fly, EffectSubtype.TopLeft, EffectTriggerType.AfterPrevious);
    IEffect effectOut = mainSequence.addEffect(smile, EffectType.Fly, EffectSubtype.BottomRight, EffectTriggerType.AfterPrevious);
    effectIn.getTiming().setDuration(2f);
    effectOut.setPresetClassType(EffectPresetClassType.Exit);

    PresentationAnimationsGenerator animationsGenerator = new PresentationAnimationsGenerator(presentation);
    try {
        animationsGenerator.setNewAnimation(animationPlayer ->
        {
            System.out.println(String.format("Animation total duration: %f", animationPlayer.getDuration()));
            animationPlayer.setTimePosition(0); // 初始动画状态
            try {
                // 初始动画状态位图
                animationPlayer.getFrame().save("firstFrame.png", ImageFormat.Png);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            animationPlayer.setTimePosition(animationPlayer.getDuration()); // 动画的最终状态
            try {
                // 动画的最后一帧
                animationPlayer.getFrame().save("lastFrame.png", ImageFormat.Png);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    } finally {
        if (animationsGenerator != null) animationsGenerator.dispose();
    }
} finally {
    if (presentation != null) presentation.dispose();
}

要让演示文稿中的所有动画一次性播放,使用 PresentationPlayer 类。该类在构造函数中接受 PresentationAnimationsGenerator 实例和效果的 FPS,然后为所有动画调用 FrameTick 事件以实现播放:

Presentation presentation = new Presentation("animated.pptx");
try {
    PresentationAnimationsGenerator animationsGenerator = new PresentationAnimationsGenerator(presentation);
    try {
        PresentationPlayer player = new PresentationPlayer(animationsGenerator, 33);
        try {
            player.setFrameTick((sender, arguments) ->
            {
                try {
                    arguments.getFrame().save("frame_" + sender.getFrameIndex() + ".png", ImageFormat.Png);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
            animationsGenerator.run(presentation.getSlides());
        } finally {
            if (player != null) player.dispose();
        }
    } finally {
        if (animationsGenerator != null) animationsGenerator.dispose();
    }
} finally {
    if (presentation != null) presentation.dispose();
}

然后可以将生成的帧编译为视频。请参阅 将 PowerPoint 转换为视频 部分。

受支持的动画和效果

入口

动画类型 Aspose.Slides PowerPoint
Appear not supported supported
Fade supported supported
Fly In supported supported
Float In supported supported
Split supported supported
Wipe supported supported
Shape supported supported
Wheel supported supported
Random Bars supported supported
Grow & Turn not supported supported
Zoom supported supported
Swivel supported supported
Bounce supported supported

强调

动画类型 Aspose.Slides PowerPoint
Pulse not supported supported
Color Pulse not supported supported
Teeter supported supported
Spin supported supported
Grow/Shrink not supported supported
Desaturate not supported supported
Darken not supported supported
Lighten not supported supported
Transparency not supported supported
Object Color not supported supported
Complementary Color not supported supported
Line Color not supported supported
Fill Color not supported supported

退出

动画类型 Aspose.Slides PowerPoint
Disappear not supported supported
Fade supported supported
Fly Out supported supported
Float Out supported supported
Split supported supported
Wipe supported supported
Shape supported supported
Random Bars supported supported
Shrink & Turn not supported supported
Zoom supported supported
Swivel supported supported
Bounce supported supported

运动路径

动画类型 Aspose.Slides PowerPoint
Lines supported supported
Arcs supported supported
Turns supported supported
Shapes supported supported
Loops supported supported
Custom Path supported supported

常见问题

是否可以转换受密码保护的演示文稿?

是的,Aspose.Slides 允许处理受密码保护的演示文稿。在处理此类文件时,您需要提供正确的密码,以便库访问演示文稿的内容。

Aspose.Slides 是否支持在云解决方案中使用?

是的,Aspose.Slides 可以集成到云应用和服务中。该库专为服务器环境设计,确保在批量处理文件时具有高性能和可伸缩性。

在转换过程中,演示文稿的大小是否有限制?

Aspose.Slides 能够处理几乎任何大小的演示文稿。然而,在处理非常大的文件时,可能需要额外的系统资源,有时建议优化演示文稿以提升性能。