Open-XML-SDK icon indicating copy to clipboard operation
Open-XML-SDK copied to clipboard

Can't Add video or audio to premade presentation

Open patolax opened this issue 1 year ago • 1 comments

Describe the bug Can't Add video or audio to premade presentations

To Reproduce This is my code, I load a PowerPoint presentation from disk and make text changes to the slide after I call these methods to add audio/video.

public void AddVideoToPresentation(PresentationDocument presentationDocument, string audioFilePath)
{
    int PicID = 915;
    PresentationPart presentationPart = presentationDocument.PresentationPart;
    var slideCount = presentationPart.Presentation.SlideIdList.Count();
    var videoEmbedId = string.Format("audioId{0}{1}", slideCount, PicID++);
    var mediaEmbedId = string.Format("medId{0}{1}", slideCount, PicID++);

    SlidePart slidepart = presentationDocument.PresentationPart.SlideParts.LastOrDefault();

    MediaDataPart mediaDataPart1 = presentationDocument.CreateMediaDataPart("audio/mp3", ".mp3");
    System.IO.Stream mediaDataPart1Stream = File.OpenRead(audioFilePath);
    mediaDataPart1.FeedData(mediaDataPart1Stream);
    mediaDataPart1Stream.Close();

    slidepart.AddAudioReferenceRelationship(mediaDataPart1, videoEmbedId);
    slidepart.AddMediaReferenceRelationship(mediaDataPart1, mediaEmbedId);

    slidepart.Slide.Save();

    AddVid(presentationDocument);
}


public void AddVid(PresentationDocument presentationDocument)
{
    PresentationPart presentationPart = presentationDocument.PresentationPart;
    SlidePart slidepart = presentationDocument.PresentationPart.AddNewPart<SlidePart>("rxId3");
    MediaDataPart mediaDataPart1 = presentationDocument.CreateMediaDataPart("video/mp4", ".mp4");
    System.IO.Stream mediaDataPart1Stream = System.IO.File.Open(@"D:\samplevideo.mp4", System.IO.FileMode.Open);
    mediaDataPart1.FeedData(mediaDataPart1Stream);
    mediaDataPart1Stream.Close();

    slidepart.AddMediaReferenceRelationship(mediaDataPart1, "rxId2");
    slidepart.AddVideoReferenceRelationship(mediaDataPart1, "rxId1");
}

Observed behavior No Video or audio embedded in the presentation

Expected behavior Play audio after slide transition

Desktop (please complete the following information):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="DocumentFormat.OpenXml" Version="2.20.0" />
    <PackageReference Include="Microsoft.Office.Interop.PowerPoint" Version="15.0.4420.1018" />
    <PackageReference Include="Mscc.GenerativeAI" Version="1.5.0" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageReference Include="OpenXmlPowerTools.NetCore" Version="1.1.0" />
    <PackageReference Include="System.ServiceModel.Syndication" Version="8.0.0" />
  </ItemGroup>

  <ItemGroup>
    <Reference Include="office">
      <HintPath>..\..\..\..\..\Windows\assembly\GAC_MSIL\office\15.0.0.0__71e9bce111e9429c\OFFICE.DLL</HintPath>
    </Reference>
  </ItemGroup>

</Project>

patolax avatar Jun 24 '24 10:06 patolax

How to add video or audio to a pre made presentation?

yswenli avatar Jul 15 '24 09:07 yswenli

Hi @yswenli Please see the sample code that adds video and audio. Code requires video, audio and picture path to be changed to match files path on your environment. The code has been produced and tested on the latest Open XML SDK 3.2.0 I see you are still using older version 2.2.0 so please update to the 3.2.0 if possible before testing the sample. Please let me know how it works for you. Thanks


using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Presentation;
using A = DocumentFormat.OpenXml.Drawing;
using P14 = DocumentFormat.OpenXml.Office2010.PowerPoint;
using ShapeTree = DocumentFormat.OpenXml.Presentation.ShapeTree;
using ShapeProperties = DocumentFormat.OpenXml.Presentation.ShapeProperties;
using NonVisualDrawingProperties = DocumentFormat.OpenXml.Presentation.NonVisualDrawingProperties;
using NonVisualPictureProperties = DocumentFormat.OpenXml.Presentation.NonVisualPictureProperties;
using NonVisualPictureDrawingProperties = DocumentFormat.OpenXml.Presentation.NonVisualPictureDrawingProperties;
using Picture = DocumentFormat.OpenXml.Presentation.Picture;
using BlipFill = DocumentFormat.OpenXml.Presentation.BlipFill;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Office2016.Drawing;


string imgEmbedId = "rId4", embedId = "rId3", mediaEmbedId = "rId2";
string filePath = @"C:\source\TestFiles\MyPresentation.pptx";
string videoFilePath = @"C:\source\TestFiles\video.mp4";
string coverPicPath = @"C:\source\TestFiles\sample.png";
string audioFilePath = @"C:\source\TestFiles\audio.mp3";

using (PresentationDocument presentationDocument = PresentationDocument.Open(filePath, true))
{

    if (presentationDocument.PresentationPart == null || presentationDocument.PresentationPart.Presentation.SlideIdList == null)
    {
        throw new NullReferenceException("Presenation Part is empty or there are no slides");
    }

    //Get presentation part
    PresentationPart presentationPart = presentationDocument.PresentationPart;

    //Get slides ids.
    OpenXmlElementList slidesIds = presentationPart.Presentation.SlideIdList.ChildElements;

    int lastSlideIndex = presentationPart.Presentation.SlideIdList.Count() - 1;

    //gets relationsipIds of the 2 last slides
    string? videoSlidePartRelationshipId = ((SlideId)slidesIds[lastSlideIndex - 1]).RelationshipId;
    string? audioSlidePartRelationshipId = ((SlideId)slidesIds[lastSlideIndex]).RelationshipId;


    if (videoSlidePartRelationshipId == null || audioSlidePartRelationshipId == null)
    {
        throw new NullReferenceException("Slides ids not found");

    }

    //Get slide part by relationshipID
    SlidePart? videoSlidepart = (SlidePart)presentationPart.GetPartById(videoSlidePartRelationshipId);
    SlidePart? audioSlidepart = (SlidePart)presentationPart.GetPartById(audioSlidePartRelationshipId);

    //Adds vide 
    AddVideo(videoSlidepart, presentationDocument);

    //Adds audio 
    AddAudio(audioSlidepart, presentationDocument);

}


void AddVideo(SlidePart slidePart, PresentationDocument presentationDocument)
{
    // Create video Media Data Part (content type, extension)
    MediaDataPart mediaDataPart = presentationDocument.CreateMediaDataPart("video/mp4", ".mp4");

    //Get the video file and feed the stream
    using (Stream mediaDataPartStream = File.OpenRead(videoFilePath))
    {
        mediaDataPart.FeedData(mediaDataPartStream);
    }
    //Adds a VideoReferenceRelationship to the MainDocumentPart
    slidePart.AddVideoReferenceRelationship(mediaDataPart, embedId);

    //Adds a MediaReferenceRelationship to the SlideLayoutPart
    slidePart.AddMediaReferenceRelationship(mediaDataPart, mediaEmbedId);

    NonVisualDrawingProperties nonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = (UInt32Value)4U, Name = "video" };
    A.VideoFromFile videoFromFile = new A.VideoFromFile() { Link = embedId };

    ApplicationNonVisualDrawingProperties appNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
    appNonVisualDrawingProperties.Append(videoFromFile);

    //Adds all the elements to the slide part
    AddMediaToTheSlide(slidePart, nonVisualDrawingProperties, appNonVisualDrawingProperties);

}

void AddAudio(SlidePart slidePart, PresentationDocument presentationDocument)
{
    // Create video Media Data Part (content type, extension)
    MediaDataPart mediaDataPart = presentationDocument.CreateMediaDataPart("audio/mp3", ".mp3");

    //Feeds the stream with audio file
    using (Stream mediaDataPartStream = File.OpenRead(audioFilePath))
    {
        mediaDataPart.FeedData(mediaDataPartStream);
    }

    slidePart.AddAudioReferenceRelationship(mediaDataPart, embedId);
    slidePart.AddMediaReferenceRelationship(mediaDataPart, mediaEmbedId);

    NonVisualDrawingProperties nonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = (UInt32Value)4U, Name = "audio" };

    A.AudioFromFile audioFromFile = new A.AudioFromFile() { Link = embedId };
    ApplicationNonVisualDrawingProperties appNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
    appNonVisualDrawingProperties.Append(audioFromFile);

    AddMediaToTheSlide(slidePart, nonVisualDrawingProperties, appNonVisualDrawingProperties);

}
void AddMediaToTheSlide(SlidePart slidePart, NonVisualDrawingProperties nonVisualDrawingProperties, ApplicationNonVisualDrawingProperties applicationNonVisualDrawingProperties)

{
    //adds sample image to the slide with id to be used as reference in blip
    ImagePart imagePart = slidePart.AddImagePart(ImagePartType.Png, imgEmbedId);
    using (Stream data = File.OpenRead(coverPicPath))
    {
        imagePart.FeedData(data);
    }

    if (slidePart!.Slide!.CommonSlideData!.ShapeTree == null)
    {
        throw new NullReferenceException("Presenation shape tree is empty");
    }

    //Getting existing shape tree object from PowerPoint
    ShapeTree shapeTree = slidePart.Slide.CommonSlideData.ShapeTree;

    // specifies the existence of a picture within a presentation.
    // It can have non-visual properties, a picture fill as well as shape properties attached to it.
    Picture picture = new Picture();
    NonVisualPictureProperties nonVisualPictureProperties = new NonVisualPictureProperties();

    //When the hyperlink text is clicked the Action is fetched
    A.HyperlinkOnClick hyperlinkOnClick = new A.HyperlinkOnClick() { Id = "", Action = "ppaction://media" };
    nonVisualDrawingProperties.Append(hyperlinkOnClick);

    NonVisualPictureDrawingProperties nonVisualPictureDrawingProperties = new NonVisualPictureDrawingProperties();
    A.PictureLocks pictureLocks = new A.PictureLocks() { NoChangeAspect = true };
    nonVisualPictureDrawingProperties.Append(pictureLocks);

    ApplicationNonVisualDrawingPropertiesExtensionList appNonVisualDrawingPropertiesExtensionList = new 
    ApplicationNonVisualDrawingPropertiesExtensionList();
    ApplicationNonVisualDrawingPropertiesExtension appNonVisualDrawingPropertiesExtension = new 
    ApplicationNonVisualDrawingPropertiesExtension() { Uri = "{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}" };

    P14.Media media = new() { Embed = mediaEmbedId };
    media.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
    appNonVisualDrawingPropertiesExtension.Append(media);
    appNonVisualDrawingPropertiesExtensionList.Append(appNonVisualDrawingPropertiesExtension);

    applicationNonVisualDrawingProperties.Append(appNonVisualDrawingPropertiesExtensionList);

    nonVisualPictureProperties.Append(nonVisualDrawingProperties);
    nonVisualPictureProperties.Append(nonVisualPictureDrawingProperties);
    nonVisualPictureProperties.Append(applicationNonVisualDrawingProperties);

    //Prepare shape properties to display picture
    BlipFill blipFill = new BlipFill();
    A.Blip blip = new A.Blip() { Embed = imgEmbedId };

    A.Stretch stretch = new A.Stretch();
    A.FillRectangle fillRectangle = new A.FillRectangle();
    A.Transform2D transform2D = new A.Transform2D();
    A.Offset offset = new A.Offset() { X = 1524000L, Y = 857250L };
    A.Extents extents = new A.Extents() { Cx = 9144000L, Cy = 5143500L };
    A.PresetGeometry presetGeometry = new A.PresetGeometry() { Preset = A.ShapeTypeValues.Rectangle };
    A.AdjustValueList adjValueList = new A.AdjustValueList();

    stretch.Append(fillRectangle);
    blipFill.Append(blip);
    blipFill.Append(stretch);
    transform2D.Append(offset);
    transform2D.Append(extents);
    presetGeometry.Append(adjValueList);

    ShapeProperties shapeProperties = new ShapeProperties();

    shapeProperties.Append(transform2D);
    shapeProperties.Append(presetGeometry);

    //adds all elements to the slide's shape tree
    picture.Append(nonVisualPictureProperties);
    picture.Append(blipFill);
    picture.Append(shapeProperties);

    shapeTree.Append(picture);

}

mkaszewiak avatar Jan 31 '25 09:01 mkaszewiak

P14.Media media = new() { Embed = mediaEmbedId };
media.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");
appNonVisualDrawingPropertiesExtension.Append(media);
appNonVisualDrawingPropertiesExtensionList.Append(appNonVisualDrawingPropertiesExtension);

Is there some chance to automatically start playing the audio when the slide is presented?

steamonimo avatar Feb 17 '25 16:02 steamonimo

Hi @steamonimo the auto play could be done with use of timing. Added auto play for both audio and video


using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Presentation;
using A = DocumentFormat.OpenXml.Drawing;
using P14 = DocumentFormat.OpenXml.Office2010.PowerPoint;
using ShapeTree = DocumentFormat.OpenXml.Presentation.ShapeTree;
using ShapeProperties = DocumentFormat.OpenXml.Presentation.ShapeProperties;
using NonVisualDrawingProperties = DocumentFormat.OpenXml.Presentation.NonVisualDrawingProperties;
using NonVisualPictureProperties = DocumentFormat.OpenXml.Presentation.NonVisualPictureProperties;
using NonVisualPictureDrawingProperties = DocumentFormat.OpenXml.Presentation.NonVisualPictureDrawingProperties;
using Picture = DocumentFormat.OpenXml.Presentation.Picture;
using BlipFill = DocumentFormat.OpenXml.Presentation.BlipFill;
using DocumentFormat.OpenXml.Packaging;
using ApplicationNonVisualDrawingProperties = DocumentFormat.OpenXml.Presentation.ApplicationNonVisualDrawingProperties;
using Command = DocumentFormat.OpenXml.Presentation.Command;

string imgEmbedId = "rId8", embedId = "rId3", mediaEmbedId = "rId2";
UInt32Value shapeId = 5;

string filePath = @"C:\source\TestFiles\MyPresentation.pptx";
string videoFilePath = @"C:\source\TestFiles\video.mp4";
string coverPicPath = @"C:\source\TestFiles\sample.png";
string audioFilePath = @"C:\source\TestFiles\audio.mp3";

using (PresentationDocument presentationDocument = PresentationDocument.Open(filePath, true))
{

    if (presentationDocument.PresentationPart == null || presentationDocument.PresentationPart.Presentation.SlideIdList == null)
    {
        throw new NullReferenceException("Presenation Part is empty or there are no slides");
    }

    //Get presentation part
    PresentationPart presentationPart = presentationDocument.PresentationPart;

    //Get slides ids.
    OpenXmlElementList slidesIds = presentationPart.Presentation.SlideIdList.ChildElements;

    int lastSlideIndex = presentationPart.Presentation.SlideIdList.Count() - 1;

    //gets relationsipIds of the 2 last slides
    string? videoSlidePartRelationshipId = ((SlideId)slidesIds[lastSlideIndex - 1]).RelationshipId;
    string? audioSlidePartRelationshipId = ((SlideId)slidesIds[lastSlideIndex]).RelationshipId;


    if (videoSlidePartRelationshipId == null || audioSlidePartRelationshipId == null)
    {
        throw new NullReferenceException("Slides ids not found");

    }

    //Get slide part by relationshipID
    SlidePart? videoSlidepart = (SlidePart)presentationPart.GetPartById(videoSlidePartRelationshipId);
    SlidePart? audioSlidepart = (SlidePart)presentationPart.GetPartById(audioSlidePartRelationshipId);

    //Adds vide 
    AddVideo(videoSlidepart, presentationDocument);

    //Adds audio 
    AddAudio(audioSlidepart, presentationDocument);

}


void AddVideo(SlidePart slidePart, PresentationDocument presentationDocument)
{
    // Create video Media Data Part (content type, extension)
    MediaDataPart mediaDataPart = presentationDocument.CreateMediaDataPart("video/mp4", ".mp4");


    //Get the video file and feed the stream
    using (Stream mediaDataPartStream = File.OpenRead(videoFilePath))
    {
        mediaDataPart.FeedData(mediaDataPartStream);
    }
    //Adds a VideoReferenceRelationship to the MainDocumentPart
    slidePart.AddVideoReferenceRelationship(mediaDataPart, embedId);

    //Adds a MediaReferenceRelationship to the SlideLayoutPart
    slidePart.AddMediaReferenceRelationship(mediaDataPart, mediaEmbedId);

    NonVisualDrawingProperties nonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = shapeId, Name = "video" };
    A.VideoFromFile videoFromFile = new A.VideoFromFile() { Link = embedId };

    ApplicationNonVisualDrawingProperties appNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
    appNonVisualDrawingProperties.Append(videoFromFile);

    //Adds all the elements to the slide part
    AddMediaToTheSlide(slidePart, nonVisualDrawingProperties, appNonVisualDrawingProperties);

}

void AddAudio(SlidePart slidePart, PresentationDocument presentationDocument)
{
    // Create video Media Data Part (content type, extension)
    MediaDataPart mediaDataPart = presentationDocument.CreateMediaDataPart("audio/mp3", ".mp3");

    //Feeds the stream with audio file
    using (Stream mediaDataPartStream = File.OpenRead(audioFilePath))
    {
        mediaDataPart.FeedData(mediaDataPartStream);
    }

    slidePart.AddAudioReferenceRelationship(mediaDataPart, embedId);
    slidePart.AddMediaReferenceRelationship(mediaDataPart, mediaEmbedId);

    NonVisualDrawingProperties nonVisualDrawingProperties = new NonVisualDrawingProperties() { Id = shapeId, Name = "audio" };

    A.AudioFromFile audioFromFile = new A.AudioFromFile() { Link = embedId };
    ApplicationNonVisualDrawingProperties appNonVisualDrawingProperties = new ApplicationNonVisualDrawingProperties();
    appNonVisualDrawingProperties.Append(audioFromFile);

    AddMediaToTheSlide(slidePart, nonVisualDrawingProperties, appNonVisualDrawingProperties);

}
void AddMediaToTheSlide(SlidePart slidePart, NonVisualDrawingProperties nonVisualDrawingProperties, ApplicationNonVisualDrawingProperties applicationNonVisualDrawingProperties)
{
    //adds sample image to the slide with id to be used as reference in blip
 ImagePart imagePart = slidePart.AddImagePart(ImagePartType.Png, imgEmbedId);
 using (Stream data = File.OpenRead(coverPicPath))
 {
     imagePart.FeedData(data);
 }

 if (slidePart!.Slide!.CommonSlideData!.ShapeTree == null)
 {
     throw new NullReferenceException("Presenation shape tree is empty");
 }

 //Getting existing shape tree object from PowerPoint
 ShapeTree shapeTree = slidePart.Slide.CommonSlideData.ShapeTree;


 // specifies the existence of a picture within a presentation.
 // It can have non-visual properties, a picture fill as well as shape properties attached to it.
 Picture picture = new Picture();
 NonVisualPictureProperties nonVisualPictureProperties = new NonVisualPictureProperties();

 A.HyperlinkOnClick hyperlinkOnClick = new A.HyperlinkOnClick() { Id = "", Action = "ppaction://media" };
 nonVisualDrawingProperties.Append(hyperlinkOnClick);

 NonVisualPictureDrawingProperties nonVisualPictureDrawingProperties = new NonVisualPictureDrawingProperties();
 A.PictureLocks pictureLocks = new A.PictureLocks() { NoChangeAspect = true };
 nonVisualPictureDrawingProperties.Append(pictureLocks);

 ApplicationNonVisualDrawingPropertiesExtensionList appNonVisualDrawingPropertiesExtensionList = new ApplicationNonVisualDrawingPropertiesExtensionList();
 ApplicationNonVisualDrawingPropertiesExtension appNonVisualDrawingPropertiesExtension = new ApplicationNonVisualDrawingPropertiesExtension() { Uri = "{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}" };

 P14.Media media = new() { Embed = mediaEmbedId };
 media.AddNamespaceDeclaration("p14", "http://schemas.microsoft.com/office/powerpoint/2010/main");

 appNonVisualDrawingPropertiesExtension.Append(media);
 applicationNonVisualDrawingProperties.Append();
 appNonVisualDrawingPropertiesExtensionList.Append(appNonVisualDrawingPropertiesExtension);

 applicationNonVisualDrawingProperties.Append(appNonVisualDrawingPropertiesExtensionList);

 nonVisualPictureProperties.Append(nonVisualDrawingProperties);
 nonVisualPictureProperties.Append(nonVisualPictureDrawingProperties);
 nonVisualPictureProperties.Append(applicationNonVisualDrawingProperties);

 //Prepare shape properties to display picture
 BlipFill blipFill = new BlipFill();
 A.Blip blip = new A.Blip() { Embed = imgEmbedId };


 A.Stretch stretch = new A.Stretch();
 A.FillRectangle fillRectangle = new A.FillRectangle();
 A.Transform2D transform2D = new A.Transform2D();
 A.Offset offset = new A.Offset() { X = 1524000L, Y = 857250L };
 A.Extents extents = new A.Extents() { Cx = 9144000L, Cy = 5143500L };
 A.PresetGeometry presetGeometry = new A.PresetGeometry() { Preset = A.ShapeTypeValues.Rectangle };
 A.AdjustValueList adjValueList = new A.AdjustValueList();

 stretch.Append(fillRectangle);
 blipFill.Append(blip);
 blipFill.Append(stretch);
 transform2D.Append(offset);
 transform2D.Append(extents);
 presetGeometry.Append(adjValueList);

 ShapeProperties shapeProperties = new ShapeProperties();

 shapeProperties.Append(transform2D);
 shapeProperties.Append(presetGeometry);

 //adds all elements to the slide's shape tree
 picture.Append(nonVisualPictureProperties);
 picture.Append(blipFill);
 picture.Append(shapeProperties);

 shapeTree.Append(picture);

 //Adding timing to the slide to allow auto play of the video and audio
 CommonTimeNode cTn = new CommonTimeNode() { Id = 1, NodeType = TimeNodeValues.TmingRoot, Duration = "indefinite" };

 ParallelTimeNode parrarelTimeNode2 = new ParallelTimeNode();
 StartConditionList stCondLst = new StartConditionList(new Condition() { Event = TriggerEventValues.OnBegin, Delay = "0" });

 //Common time node of type AfterEffect to play automaicly with commnd to play from 0.0
 CommonTimeNode cTn2 = new CommonTimeNode(stCondLst) { Id = 2, PresetId = 1, PresetClass = TimeNodePresetClassValues.MediaCall, PresetSubtype = 0, NodeType = TimeNodeValues.AfterEffect, Fill = TimeNodeFillValues.Hold };
 ChildTimeNodeList chTnLst2 = new ChildTimeNodeList();
 TargetElement targetElement = new TargetElement();
 ShapeTarget shapeTarget = new ShapeTarget() { ShapeId = shapeId.ToString() };
 Command command = new Command() { Type = CommandValues.Call, CommandName = "playFrom(0.0)" };
 CommonBehavior cBhvr = new CommonBehavior(new CommonTimeNode() { Id = 2 });
 targetElement.Append(shapeTarget);
 cBhvr.Append(targetElement);
 command.Append(cBhvr);
 chTnLst2.Append(command);
 cTn2.Append(chTnLst2);

 SequenceTimeNode sequenceTimeNode = new SequenceTimeNode() { Concurrent = true, NextAction = NextActionValues.Seek };
 sequenceTimeNode.Append(cTn2);

 ChildTimeNodeList chTnLst = new ChildTimeNodeList();
 chTnLst.Append(sequenceTimeNode);

 cTn.Append(chTnLst);

 ParallelTimeNode parrarelTimeNode = new ParallelTimeNode();
 parrarelTimeNode.Append(cTn);

 TimeNodeList tnLst = new TimeNodeList();
 tnLst.Append(parrarelTimeNode);

 Timing timing = new Timing();
 timing.Append(tnLst);

 Slide slide = slidePart.Slide;
 slide.Append(timing);

}

Thanks

mkaszewiak avatar Feb 21 '25 20:02 mkaszewiak

Thank you very much! But there is one catch with your code.

It saves the media at root\media in the resulting ZIP.

However, if you save the resulting file in PowerPoint it takes the mp3 from root\media and copies them to root\ppt\media and then there is still an old copy remaining in root\media. In the copy process PowerPoint renames all relation IDs that pointed to the previous location. If you then reopen this file again with your code it will again save to root\media.

So far this does not cause issues but after operating multiple times on the PowerPoint file it will contain multiple copies of the same MP3 file.

steamonimo avatar Feb 22 '25 00:02 steamonimo

Hi @steamonimo I see that PPT removes old mp3/mp4 files whenever saving directly from PPT. see the attached screenshot (Red is removed and green is added)

Image

mkaszewiak avatar Feb 23 '25 15:02 mkaszewiak

We consider this as answered. Closing this issue

mkaszewiak avatar Feb 24 '25 16:02 mkaszewiak

We consider this as answered. Closing this issue

Three problems still remain:

  • Office 365 will not cleanup root\media - in contrast to what you are experiencing
  • Opening the old 2006 scheme with Office 365, modifying and saving afterwards will result in a file that does not play automatically anymore (just load edit save and reload > audio does not play).
  • In 2014 scheme files converted with Office 365 I had to manually remove all objects of type AlternateContent with slidePart.Slide.Descendants to prevent that multiple instances of transition elements will be created when reprocessing the file. The under the hood transformation by Office 365 really become messy.

steamonimo avatar Feb 24 '25 20:02 steamonimo

Hi @steamonimo thank you for your input on this. For the first bullet point I am also using Office 365 and see it removed additionally we tested it internally on 2 different machines and we see the old files removed. Possibly can you share your file sample so we can investigate.? For the second bullet can you share sample file so I can test and adjust code where possible. Could you explain bit more on last bullet what exactly are you doing (repro steps) and share the sample file as well. Thanks

mkaszewiak avatar Feb 25 '25 09:02 mkaszewiak

@mkaszewiak: I contacted you via mail...

steamonimo avatar Feb 25 '25 11:02 steamonimo

Hi @steamonimo I didn't receive any email from you.

mkaszewiak avatar Feb 25 '25 11:02 mkaszewiak

Hi @steamonimo I didn't receive any email from you.

Thanks for letting me know. I tried again without attachments...

steamonimo avatar Feb 25 '25 12:02 steamonimo

@steamonimo I have it now. Will update you once will have an update on it. Thanks

mkaszewiak avatar Feb 25 '25 13:02 mkaszewiak

Hi @steamonimo I see the working file you have provided in the email narrate_working_EN.pptx file has errors related to the slide transition and this is causing the issue later when you save in PPT. As transition is something different to audio and video could you please open new issue as we don't want to mix multiple issues under one thread to avoid confusion and I will take it from there. Thanks

Image

mkaszewiak avatar Feb 25 '25 14:02 mkaszewiak