scanny / python-pptx

Create Open XML PowerPoint documents in Python

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to access and create media objects

hros opened this issue · comments

commented

I want to add audio files to slides by inserting an audio object that plays an audio file
image
How can this be accomplished using the python-pptx package?

I added an audio object to a slide (named "Recorded Sound") and tried to find it from the slide object, but it wasn't part of the shapes list.

How can access existing audio objects, and add additional objects to a slide?

Hi believe some folks have had success using shapes.add_movie() for that. Have a search around on "python-pptx add mp3" or similar search terms and I think you'll find some ideas.

commented

thanks!

even if shapes.add_movie can add a new mp3 audio object (as described in this post), I still don't see how to:

  1. find an existing audio object from the slide object, and either delete it or update the link to the audio file
  2. set properties of audio object, enable: hide during playback and start automatically

Yes, I've done it that way: Lines 2889 to 2896 in md2pptx show an example of doing that. Nowhere in md2pptx do I do anything different for media that turns out to be audio compared to video. (Yes, I parse HTML / markdown input that points at them separately, but that's not relevant.)

commented

Yes, I've done it that way: Lines 2889 to 2896 in md2pptx show an example of doing that. Nowhere in md2pptx do I do anything different for media that turns out to be audio compared to video. (Yes, I parse HTML / markdown input that points at them separately, but that's not relevant.)

thanks, but unfortunately the example can only create new media objects, while I would like to access and update existing media objects

commented

is there a "raw XML" API that lets me access everything in the slide, albeit in a non-friendly manner?

It's an implementation detail, so use at your own risk, but I think what you're talking about is what we call the "oxml" layer. Like Slide has ._element which is the lxml.etree._Element object for the <p:sld> element that is the root of the XML tree for the slide.

Using these is how all the proxy classes (e.g. Slide) operate on the XML and it's not uncommon for folks to do the same when they need to extend the behaviors somehow.

The basic strategy is to get as close to your target spot in the XML using the proxies, so maybe slide.shapes._grpSp and then use lxml.etree._Element methods from there.

commented

thanks!
I inserted a Media/Audio object in one of the slides, and I parsed it with python-pptx, but I couldn't find it
How do you suggest I traverse all the elements of the slide? Do I start with slide._element and work my way down the tree with .getchildren()?

By the way, I unzipped the presentation (the pptx file) and viewed the XML tree of the slide (slides/slide2.xml) which contains a blank slide with an audio element with an online XML viewer. The element is named "Recorded Sound."
How would you access this element using either slide._element or slide.shapes.grpSp?
I found that slide._element.getchildren()[0].getchildren()[0].getchildren()[2].getchildren()[0].getchildren()[0].name == 'Recorded Sound', is that the proper way to do it? How would I find it easily in general when there are other elements in the slide?
Can you share a link to an example that changes the properties of the elements using the XML API?

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:sld
  xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
  xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
  <p:cSld>
    <p:spTree>
      <p:nvGrpSpPr>
        <p:cNvPr id="1" name=""/>
        <p:cNvGrpSpPr/>
        <p:nvPr/>
      </p:nvGrpSpPr>
      <p:grpSpPr>
        <a:xfrm>
          <a:off x="0" y="0"/>
          <a:ext cx="0" cy="0"/>
          <a:chOff x="0" y="0"/>
          <a:chExt cx="0" cy="0"/>
        </a:xfrm>
      </p:grpSpPr>
      <p:pic>
        <p:nvPicPr>
          <p:cNvPr id="2" name="Recorded Sound">
            <a:hlinkClick r:id="" action="ppaction://media"/>
            <a:extLst>
              <a:ext uri="{FF2B5EF4-FFF2-40B4-BE49-F238E27FC236}">
                <a16:creationId
                  xmlns:a16="http://schemas.microsoft.com/office/drawing/2014/main" id="{42CC0928-1512-980B-37E2-51D82FC53C63}"/>
                </a:ext>
              </a:extLst>
            </p:cNvPr>
            <p:cNvPicPr>
              <a:picLocks noChangeAspect="1"/>
            </p:cNvPicPr>
            <p:nvPr>
              <a:audioFile r:link="rId2"/>
              <p:extLst>
                <p:ext uri="{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}">
                  <p14:media
                    xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" r:embed="rId1"/>
                  </p:ext>
                </p:extLst>
              </p:nvPr>
            </p:nvPicPr>
            <p:blipFill>
              <a:blip r:embed="rId4"/>
              <a:stretch>
                <a:fillRect/>
              </a:stretch>
            </p:blipFill>
            <p:spPr>
              <a:xfrm>
                <a:off x="5892800" y="3225800"/>
                <a:ext cx="406400" cy="406400"/>
              </a:xfrm>
              <a:prstGeom prst="rect">
                <a:avLst/>
              </a:prstGeom>
            </p:spPr>
          </p:pic>
        </p:spTree>
        <p:extLst>
          <p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}">
            <p14:creationId
              xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="472980364"/>
            </p:ext>
          </p:extLst>
        </p:cSld>
        <p:clrMapOvr>
          <a:masterClrMapping/>
        </p:clrMapOvr>
        <p:timing>
          <p:tnLst>
            <p:par>
              <p:cTn id="1" dur="indefinite" restart="never" nodeType="tmRoot">
                <p:childTnLst>
                  <p:seq concurrent="1" nextAc="seek">
                    <p:cTn id="2" dur="indefinite" nodeType="mainSeq">
                      <p:childTnLst>
                        <p:par>
                          <p:cTn id="3" fill="hold">
                            <p:stCondLst>
                              <p:cond delay="indefinite"/>
                            </p:stCondLst>
                            <p:childTnLst>
                              <p:par>
                                <p:cTn id="4" fill="hold">
                                  <p:stCondLst>
                                    <p:cond delay="0"/>
                                  </p:stCondLst>
                                  <p:childTnLst>
                                    <p:par>
                                      <p:cTn id="5" presetID="1" presetClass="mediacall" presetSubtype="0" fill="hold" nodeType="clickEffect">
                                        <p:stCondLst>
                                          <p:cond delay="0"/>
                                        </p:stCondLst>
                                        <p:childTnLst>
                                          <p:cmd type="call" cmd="playFrom(0.0)">
                                            <p:cBhvr>
                                              <p:cTn id="6" dur="3797" fill="hold"/>
                                              <p:tgtEl>
                                                <p:spTgt spid="2"/>
                                              </p:tgtEl>
                                            </p:cBhvr>
                                          </p:cmd>
                                        </p:childTnLst>
                                      </p:cTn>
                                    </p:par>
                                  </p:childTnLst>
                                </p:cTn>
                              </p:par>
                            </p:childTnLst>
                          </p:cTn>
                        </p:par>
                      </p:childTnLst>
                    </p:cTn>
                    <p:prevCondLst>
                      <p:cond evt="onPrev" delay="0">
                        <p:tgtEl>
                          <p:sldTgt/>
                        </p:tgtEl>
                      </p:cond>
                    </p:prevCondLst>
                    <p:nextCondLst>
                      <p:cond evt="onNext" delay="0">
                        <p:tgtEl>
                          <p:sldTgt/>
                        </p:tgtEl>
                      </p:cond>
                    </p:nextCondLst>
                  </p:seq>
                  <p:audio>
                    <p:cMediaNode vol="80000">
                      <p:cTn id="7" fill="hold" display="0">
                        <p:stCondLst>
                          <p:cond delay="indefinite"/>
                        </p:stCondLst>
                        <p:endCondLst>
                          <p:cond evt="onStopAudio" delay="0">
                            <p:tgtEl>
                              <p:sldTgt/>
                            </p:tgtEl>
                          </p:cond>
                        </p:endCondLst>
                      </p:cTn>
                      <p:tgtEl>
                        <p:spTgt spid="2"/>
                      </p:tgtEl>
                    </p:cMediaNode>
                  </p:audio>
                </p:childTnLst>
              </p:cTn>
            </p:par>
          </p:tnLst>
        </p:timing>
      </p:sld>