一种导出PPT到MP4的方法

news2024/9/21 18:43:19

需求

导出PPT到MP4,并记录每页,每个动作的时间线。通过 MP4+时间线 就可以在页面上很方便的放映PPT的内容,并支持翻页点击。

代码

保存每一页的图像信息,用做播放器的缩略图

public void SaveThumbnail(string ppt_filepath, string targetdir)

记录下时间线

public void ResetTimeline(string ppt_filepath,string targetdir)

 打开PPT并绑定事件

            presentation = PPT.Presentations.Open(fn, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoTrue);
            PPT.SlideShowBegin += SlideShowBeginEvent;//开始运行PPT
            PPT.SlideShowEnd += SlideShowEndEvent;//开始运行PPT
            PPT.SlideShowNextSlide += SlideShowNextSlideEvent;//PPT翻页事件 
            PPT.SlideShowNextClick += SlideShowNextClickEvent;
            PPT.WindowActivate += WindowActivateEvent;

开始播放

            presentation.SlideShowSettings.AdvanceMode = PpSlideShowAdvanceMode.ppSlideShowRehearseNewTimings;
            presentation.SlideShowSettings.ShowWithNarration = MsoTriState.msoFalse;
            presentation.SlideShowSettings.ShowMediaControls = MsoTriState.msoTrue;
            presentation.SlideShowSettings.Run();

保存MP4文件

 presentation.CreateVideo(fn_mp4, true, 1, 720);

保存时间线json

            string json = Newtonsoft.Json.JsonConvert.SerializeObject(list_TimeRec);
            string json_fn = Path.ChangeExtension(fn_mp4,".json");
            File.WriteAllText(json_fn, json); 

全部代码

    public class PPTTools
    {
        public static void ClosePPT()
        {
            Process[] powerPointProcesses = Process.GetProcessesByName("powerpnt");
            foreach (Process powerPointProcess in powerPointProcesses)
            {
                try
                {
                    // 尝试关闭进程,并等待一段时间
                    powerPointProcess.CloseMainWindow();
                    powerPointProcess.WaitForExit(1000);
                    // 如果进程仍然没有关闭,强制结束
                    if (!powerPointProcess.HasExited)
                    {
                        powerPointProcess.Kill();
                    }
                }
                catch (Exception ex)
                {
                    //无法关闭PowerPoint进程
                }
            }
        }

        public void SaveThumbnail(string ppt_filepath, string targetdir)
        {
            ClosePPT();

            string tmpdir = get_tmpdir();
            string fn = Path.GetFileNameWithoutExtension(ppt_filepath) + "_tmp" + Path.GetExtension(ppt_filepath);
            fn = Path.Combine(tmpdir, fn);
            File.Copy(ppt_filepath, fn, true);

            list_TimeRec.Clear();
            will_next = false;
            PPT = new Microsoft.Office.Interop.PowerPoint.Application();
            presentation = null;
            presentation = PPT.Presentations.Open(fn, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoTrue);

            for (int i = 1; i <= presentation.Slides.Count; i++)
            {
                string thumbnail_fn = presentation.Slides[i].SlideNumber.ToString() + ".jpg";
                thumbnail_fn = Path.Combine(targetdir, thumbnail_fn);
                presentation.Slides[i].Export(thumbnail_fn, "JPG",1280);

            }

            PPT.Quit();
            ClosePPT();
        }

        public static string exefilename()
        {
            return System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
        }
        public static string get_tmpdir()
        {
            string dir = Path.GetDirectoryName(exefilename());
            dir = Path.Combine(dir, "temp");
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);
            return dir;
        }
        private bool is_Timeline = false;
        private bool is_Completed = false;
        private DateTime SlideShowNextSlideEvent_Time;
        private bool will_next = false;
        private Microsoft.Office.Interop.PowerPoint.Application PPT = null;
        private Presentation presentation = null;
        private SlideShowWindow CurrShowWindow;
        private List<TimeRec> list_TimeRec = new List<TimeRec>();
        public void ResetTimeline(string ppt_filepath,string targetdir)
        {
            if (is_Timeline)
                return;
            is_Timeline = true;
            is_Completed = false;
            ClosePPT();
           
            string tmpdir = get_tmpdir();
            string fn = Path.GetFileNameWithoutExtension(ppt_filepath )+ "_tmp" + Path.GetExtension(ppt_filepath);
            fn = Path.Combine(tmpdir, fn);
            File.Copy(ppt_filepath, fn, true);

            list_TimeRec.Clear();
            will_next = false;
            PPT = new Microsoft.Office.Interop.PowerPoint.Application();
            presentation = null;
            presentation = PPT.Presentations.Open(fn, MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoTrue);
            PPT.SlideShowBegin += SlideShowBeginEvent;//开始运行PPT
            PPT.SlideShowEnd += SlideShowEndEvent;//开始运行PPT
            PPT.SlideShowNextSlide += SlideShowNextSlideEvent;//PPT翻页事件 
            PPT.SlideShowNextClick += SlideShowNextClickEvent;
            PPT.WindowActivate += WindowActivateEvent;

            //presentation.SlideShowSettings.LoopUntilStopped = MsoTriState.msoFalse;
            presentation.SlideShowSettings.AdvanceMode = PpSlideShowAdvanceMode.ppSlideShowRehearseNewTimings;
            presentation.SlideShowSettings.ShowWithNarration = MsoTriState.msoFalse;
            presentation.SlideShowSettings.ShowMediaControls = MsoTriState.msoTrue;
            presentation.SlideShowSettings.Run();
            System.Windows.Forms.Application.DoEvents();

            while (!is_Completed)
            { 
                System.Windows.Forms.Application.DoEvents();
                System.Threading.Thread.Sleep(10);
                if (will_next)
                {                   
                    if ((DateTime.Now - SlideShowNextSlideEvent_Time).TotalMilliseconds > 1000 * 8)
                    {
                        will_next = true;
                        SlideShowNextSlideEvent_Time = DateTime.Now;
                        int ClickCount = CurrShowWindow.View.GetClickCount();
                        int ClickIndex = CurrShowWindow.View.GetClickIndex();
                        if (ClickCount <= 0)
                        {
                            if (CurrShowWindow.View.Slide.SlideIndex == presentation.Slides.Count  )
                            {
                                break;
                            }
                            CurrShowWindow.View.Next();
                        }
                        else
                        {
                            if (ClickIndex <= (ClickCount -1))
                            {
                                CurrShowWindow.View.GotoClick(ClickIndex + 1);
                                //add_rec(ShowWindow);
                                SlideShowNextSlideEvent_Time = DateTime.Now; 
                            }
                            else
                            {
                                if (CurrShowWindow.View.Slide.SlideIndex == presentation.Slides.Count  )
                                {
                                    break;
                                }
                                else
                                {
                                    CurrShowWindow.View.Next();
                                }
                            }
                        }
                    }
                }
            }
            exited = false;
            Thread trd = new Thread( this.thread_proc );
            trd.Start();
            CurrShowWindow.View.Exit();
            exited = true;

            presentation.Save();
            if (!System.IO.Directory.Exists(targetdir))
                System.IO.Directory.CreateDirectory(targetdir);

            string fn_mp4 =Path.ChangeExtension( Path.Combine(targetdir, Path.GetFileName(ppt_filepath)),".mp4");

            presentation.CreateVideo(fn_mp4, true, 1, 720);
            for (int i = 0; i < 20; i++)
            {
                System.Windows.Forms.Application.DoEvents();
                System.Threading.Thread.Sleep(100);
            }
            while (presentation.CreateVideoStatus == PpMediaTaskStatus.ppMediaTaskStatusInProgress)
            {
                System.Windows.Forms.Application.DoEvents();
                System.Threading.Thread.Sleep(10);
            }
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(list_TimeRec);
            string json_fn = Path.ChangeExtension(fn_mp4,".json");
            File.WriteAllText(json_fn, json); 
             
            ClosePPT();
            is_Timeline = false;
        }
        private bool exited = false;
        public void thread_proc()
        {
            while (!exited)
            {
                try
                {

                    System.Threading.Thread.Sleep(100);
                    IntPtr h = IntPtr.Zero;
                    h = FindWindow(null, "Microsoft PowerPoint");
                    if (h != IntPtr.Zero)
                    {
                        ForceWindowIntoForeground(h);//置顶   
                        SendKeys.SendWait("\r");
                        SendKeys.SendWait(" ");
                    }
                    else
                    {
                    }
                }
                catch (Exception err)
                {

                }
                Thread.Sleep(500);
            }
        }
        public void SlideShowBeginEvent(SlideShowWindow Wn)
        {
        }
        public void SlideShowEndEvent(Presentation Pres)
        {
            is_Completed = true;
        }
        public void add_rec(SlideShowWindow Wn,string Event)
        {
            Slide slide = Wn.View.Slide;
            TimeRec rec = new TimeRec();
            rec.Event = Event;
            rec.ShowPosition = Wn.View.CurrentShowPosition;
            rec.PresentationElapsedTime = Wn.View.PresentationElapsedTime;
            rec.SlideElapsedTime = Wn.View.SlideElapsedTime;
            rec.SlideIndex = slide.SlideIndex;
            rec.SlideNumber = slide.SlideNumber;
            rec.ClickCount = Wn.View.GetClickCount();
            rec.ClickIndex = Wn.View.GetClickIndex();
            list_TimeRec.Add(rec);
        }

        public void SlideShowNextSlideEvent(SlideShowWindow Wn)
        {
            add_rec(Wn, "NextSlide");
            CurrShowWindow = Wn;
            SlideShowNextSlideEvent_Time = DateTime.Now ;
            will_next = true;
        }
        public void SlideShowNextClickEvent(SlideShowWindow Wn, Effect nEffect) {
            add_rec(Wn, "NextClick");
            CurrShowWindow = Wn;
            SlideShowNextSlideEvent_Time = DateTime.Now;
            will_next = true;
        }
        public void WindowActivateEvent(Presentation Pres, DocumentWindow Wn)
        { 
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
        //I'd double check this constant, just in case
        static uint WM_CLOSE = 0x10;
        public void CloseWindow(IntPtr hWindow)
        {
            SendMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }
        [DllImport("USER32.DLL")]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        public const int HWND_TOP = 0;
        public const int HWND_BOTTOM = 1;
        public const int HWND_TOPMOST = -1;
        public const int HWND_NOTOPMOST = -2;
        public struct WindowRect
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
        private const int SW_HIDE = 0;
        private const int SW_SHOWNORMAL = 1;
        private const int SW_NORMAL = 1;
        private const int SW_SHOWMINIMIZED = 2;
        private const int SW_SHOWMAXIMIZED = 3;
        private const int SW_MAXIMIZE = 3;
        private const int SW_SHOWNOACTIVATE = 4;
        private const int SW_SHOW = 5;
        private const int SW_MINIMIZE = 6;
        private const int SW_SHOWMINNOACTIVE = 7;
        private const int SW_SHOWNA = 8;
        private const int SW_RESTORE = 9;
        private const int SW_SHOWDEFAULT = 10;
        private const int SW_MAX = 10;

        private const int SPI_GETFOREGROUNDLOCKTIMEOUT = 0x2000;
        private const int SPI_SETFOREGROUNDLOCKTIMEOUT = 0x2001;
        private const int SPIF_SENDCHANGE = 0x2; 
       

        [DllImport("user32.dll", SetLastError = true)]
        static extern bool SystemParametersInfo(int uiAction, int uiParam, ref uint pvParam, int fWinIni);

        [DllImport("user32.dll")]
        private static extern IntPtr AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, Boolean fAttach);

        [DllImport("user32", EntryPoint = "GetWindowThreadProcessId")]
        private static extern IntPtr GetWindowThreadProcessId(IntPtr hwnd, out IntPtr lpdwProcessId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();

        [DllImport("kernel32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        public static extern IntPtr GetCurrentThreadId();

        [DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);//设置此窗体为活动窗体

        [DllImport("user32.dll")]
        public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint wFlags);


        [DllImport("user32.dll")]
        public static extern bool GetWindowRect(IntPtr hWnd, out WindowRect lpRect);
        [DllImport("user32", CharSet = CharSet.Auto)]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        public static void SetTopomost(IntPtr hWnd)
        {
            WindowRect rect = new WindowRect();
            GetWindowRect(hWnd, out rect);
            SetWindowPos(hWnd, (IntPtr)HWND_TOPMOST, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, 0);
        }
        public static void ForceWindowIntoForeground(IntPtr window)
        {
            try
            {
                SetTopomost(window);
                IntPtr currentThread = GetCurrentThreadId();

                IntPtr activeWindow = GetForegroundWindow();
                IntPtr activeProcess;
                IntPtr activeThread = GetWindowThreadProcessId(activeWindow, out activeProcess);

                IntPtr windowProcess;
                IntPtr windowThread = GetWindowThreadProcessId(window, out windowProcess);

                if (currentThread != activeThread)
                    AttachThreadInput(currentThread, activeThread, true);
                if (windowThread != currentThread)
                    AttachThreadInput(windowThread, currentThread, true);

                uint oldTimeout = 0, newTimeout = 0;
                SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0);
                SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref newTimeout, 0);
                // LockSetForegroundWindow(LSFW_UNLOCK);
                // AllowSetForegroundWindow(ASFW_ANY);

                SetForegroundWindow(window);
                ShowWindow(window, SW_RESTORE);

                SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0);

                if (currentThread != activeThread)
                    AttachThreadInput(currentThread, activeThread, false);
                if (windowThread != currentThread)
                    AttachThreadInput(windowThread, currentThread, false);

                SetTopomost(window);

            }
            catch (Exception e)
            {


            }

        }

    }

    public class TimeRec
    { 
        public string Event = "";
        public int ShowPosition = 0;
        public float PresentationElapsedTime = 0;
        public float SlideElapsedTime = 0;
        public int SlideIndex = 0;
        public int SlideNumber = 0;
        public int ClickCount = 0;
        public int ClickIndex = 0;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2082112.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STL】红黑树的全面探索与红黑树的实现

ps&#xff1a;文章最后有完整的代码 1.红黑树的概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路…

如何使用IDEA搭建Mybatis框架环境

文章目录 ☕前言为什么学习框架技术Mybatis框架简介 &#x1f379;一、如何配置Mybatis框架环境1.1下载需要MyBatis的jar文件1.2部署jar文件1.3创建MyBatis核心配置文件configuration.xml1.4.创建持久类(POJO)和SQL映射文件1.5.创建测试类 &#x1f9cb;二、 MyBatis框架的优缺…

前端性能优化:使用Vue3+TS+Canvas对图片进行压缩后再上传,优化带宽,减小服务器存储成本,减少流量损耗

在上传图片之前&#xff0c;对图片进行压缩。看到这里是不是有点懵&#xff0c;前端怎么压缩图片呢&#xff0c;这不应该是后端做的吗&#xff1f; 但是我在开发的时候接到了这样一个需求&#xff0c;要求对用户上传的图片进行一定的压缩&#xff0c;而且并且尽量还原图片的清…

大模型如何改变世界?李彦宏:未来至少一半人要学会“提问题“

2023年爆火的大模型&#xff0c;对我们来说意味着什么&#xff1f; 百度创始人、董事长兼CEO李彦宏认为&#xff0c;“大模型即将改变世界。” 5月26日&#xff0c;李彦宏参加了在北京举办的2023中关村论坛&#xff0c;发表了题为《大模型改变世界》的演讲。李彦宏认为&#…

2024年新算法-基于SBOA-BP混合神经网络的数据预测(Python代码实现)

在今天的数字化时代&#xff0c;机器学习和人工智能领域的不断发展为数据处理和预测提供了强大的工具。其中&#xff0c;BP神经网络&#xff08;反向传播神经网络&#xff09;作为一种经典的网络模型&#xff0c;因其能够处理复杂的非线性问题而备受关注。然而&#xff0c;传统…

吴恩达机器学习课后作业-07kmeans and pca

k-均值与PCA k-均值图片颜色聚类 PCA&#xff08;主成分分析&#xff09;对x去均值化图像降维 k-均值 K-均值是最普及的聚类算法&#xff0c;算法接受一个未标记的数据集&#xff0c;然后将数据聚类成不同的组。 K-均值是一个迭代算法&#xff0c;假设我们想要将数据聚类成n个…

python-变量声明、数据类型、标识符

一.变量 1.什么是变量 为什么需要变量呢&#xff1f; 一个程序就是一个世界&#xff0c;不论使用哪种高级程序语言编写代码&#xff0c;变量都是其程序的基本组成单位。如下图所示的sum和sub都是变量。 变量的定义&#xff1a; 变量相当于内存中一个数据存储空间的表示&#…

Spring MVC常用注解及用法

目录 1.建立连接--RequestMapping 2.请求 2.1 传递单个参数 2.2 传递多个参数 2.3 传递对象 2.4 参数重命名--RequestParam 2.5 传递数组 2.6 传递集合 2.7 传递json数据--RequestBody 2.8 获取URL中参数--PathVariable 2.9 上传文件--RequestPart 2.10 获取Cookie--…

bomb 实验

GDB常用命令&#xff1a; GDB调试常用命令-CSDN博客 原理&#xff1a; 编译与反汇编过程-CSDN博客 Bomb实验实现 阶段一&#xff1a; 分析 分配空间&#xff1a;sub $0x8,%rsp 为局部变量分配栈空间。设置参数&#xff1a;mov $0x402400,%esi 将字符串地址加载到 %esi。…

MMsegmentation与MMdeploy简单使用

最近涉及到了图像分割的任务&#xff0c;于是拿来写下博客加深下使用。 MMsegmentation与MMdeploy的环境配置暂不做讲解&#xff0c;在官网和其他博客中有很多说明。 MMdeploy主要是把pt转为 onnx_int8的情况。 MMsegmentation环境配置可以参考 : 安装与配置MMSegmentation 目录…

【管理型文档】软件需求管理过程(原件)

软件需求管理规程应明确需求收集、分析、确认、变更控制及验证等流程&#xff0c;确保需求准确反映用户期望&#xff0c;支撑软件开发。该规程要求系统记录需求来源&#xff0c;通过评审确保需求完整、清晰、无歧义&#xff0c;实施变更控制以维护需求基线稳定&#xff0c;并持…

后端面试真题整理

面试问题整理 本人主要记录2024年秋招、春招过程中的疑难八股真题&#xff0c;参考来源&#xff1a;牛客网、知乎等。 八股 深拷贝与浅拷贝 浅拷贝&#xff1a; 浅拷贝会在堆上创建一个新的对象&#xff08;区别于引用拷贝的一点&#xff09;&#xff0c;不过&#xff0c;如果…

井盖丢失隐患大?智慧井盖监管系统帮你解决

在现代都市中&#xff0c;我们每天行走在钢筋水泥之间&#xff0c;却很少有人注意到脚下的小小井盖。这些不起眼的圆形铁盘不仅是城市地下管网的入口&#xff0c;更是维系城市生命线的重要组成部分。然而&#xff0c;当暴雨来袭&#xff0c;或是深夜无人之时&#xff0c;井盖的…

无线麦克风什么牌子的音质效果好?一文读懂麦克风哪个牌子的好

无线领夹麦克风哪款音质最好&#xff1f;在这个追求高质量音效的年代&#xff0c;选择一款合适的无线领夹麦克风&#xff08;简称领夹麦&#xff09;对于提升录音或直播的音质至关重要。随着市场的不断扩大&#xff0c;市面上充斥着大量信号不稳定、音质差的无线领夹麦克风&…

2024年汽车零部件企业CRM研究:服务商排名、案例分析、需求分析

最近媒体上频现各车企大佬发声&#xff0c;抗议某汽车企业“不要卷价格&#xff0c;要卷长期价值”&#xff0c;还有的直接批判其打破行业规则。图穷匕现&#xff0c;汽车行业的竞争愈发激烈了。 汽车产业作为我国国民经济的重要支柱产业、经济增长和转型的重要抓手&#xff0…

微软将持续多年的 Mono 项目移交给 Wine

今天&#xff0c;微软突然决定将 Mono 项目交由 Wine 开发社区管理。自Mono项目上一次作为开源.NET框架发布以来&#xff0c;已经过去了五年时间&#xff0c;此前Wine已经使用了Mono的代码&#xff0c;而在微软专注于开源.NET和其他工作的情况下&#xff0c;此举是合理的&#…

Python编程的终极十大工具(非常详细)零基础入门到精通,收藏这一篇就够了

&#x1f91f; 基于入门网络安全打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 Python一直以来都是程序员们的首选编程语言之一&#xff0c;其灵活性和功能强大的库使其成为解决各种问题的理想选择。在本文中&#xff0c;我们将介绍Python编程的终…

fdMemTable内存表进行SQL查询

fdLocalSql可以对fdMemTable内存表进行SQL查询&#xff08;可以对多个fdMemTable内存表进行联表查询哦&#xff09;&#xff0c;fdLocalSql使用SQLITE引擎&#xff0c;而FIREDAC驱动SQLITE&#xff0c;连SQLITE驱动DLL都不需要附带的。 所有设置用FormCreate里用代码 procedure…

【C#】Visual Studio2017 MSDN离线安装

1. 运行Visual Studio Installer 在Windows的开始菜单中直接搜索 2. 单击“修改”按钮 3. 依次点击&#xff0c;单个组件 - 代码工具 - Help Viewer - 修改&#xff0c;开始安装 4. 下载速度慢解决方法 修改IPv4 DNS 参考&#xff1a;visual studio下载慢解决方法&#xf…

unity脚本

Transform.Rotate 描述 使用 Transform.Rotate 以各种方式旋转 GameObjects。通常以欧拉角而不是四元数提供旋转。 可以在世界轴或本地轴中指定旋转。 世界轴旋转使用 Scene 的坐标系&#xff0c;因此在开始旋转 GameObject 时&#xff0c;它的 x、y 和 z 轴与 x、y 和 z 世…