scanny / python-pptx

Create Open XML PowerPoint documents in Python
MIT License
2.39k stars 517 forks source link

Cannot add video slide, if another slide layout in the master template has a mp3 media #323

Open ajeshp opened 6 years ago

ajeshp commented 6 years ago

I think I discovered an issue

Since we cannot add mp3 media using the pptx library, I added a layout with what I wanted and a mp3 media.  Once I do this, when I tried to add a mp4 video, I get the below error. This is easily reproduced. The error goes away once you delete the mp3 media for the slide layout.:

Traceback (most recent call last):   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\util.py", line 134, in get_prop_value     return getattr(obj, cache_attr_name) AttributeError: '_MoviePicElementCreator' object has no attribute '__pic' During handling of the above exception, another exception occurred: Traceback (most recent call last):   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\util.py", line 134, in get_prop_value     return getattr(obj, cache_attr_name) AttributeError: '_MoviePicElementCreator' object has no attribute '__video_part_rIds' During handling of the above exception, another exception occurred: Traceback (most recent call last):   File "sai_ppt.py", line 68, in generatePrs     makePrs(self.prsDict)   File "C:\Users\ajesh\final\make_prs.py", line 120, in make_prs     init_video_slide(prs_d, prs)   File "C:\Users\ajesh\final\make_prs.py", line 167, in init_video_slide     make_media_slide(prs, slide_text, video_file, layout_idx)   File "C:\Users\ajesh\final\make_prs.py", line 80, in make_media_slide     movie = slide.shapes.add_movie(media, Inches(1.5), Inches(1.25), Inches(10), Inches(5), poster_frame_fn, "Video/mp4")   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\shapes\shapetree.py", line 485, in add_movie     poster_frame_image, mime_type   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\shapes\shapetree.py", line 717, in new_movie_pic     mime_type   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\util.py", line 136, in get_prop_value     value = f(obj)   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\shapes\shapetree.py", line 734, in _pic     self._shape_id, self._shape_name, self._video_rId,   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\shapes\shapetree.py", line 802, in _video_rId     return self._video_part_rIds[1]   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\util.py", line 136, in get_prop_value     value = f(obj)   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\shapes\shapetree.py", line 791, in _video_part_rIds     self._video   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\parts\slide.py", line 188, in get_or_add_video_media_part     media_part = self._package.get_or_add_media_part(video)   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\package.py", line 58, in get_or_add_media_part     return self._media_parts.get_or_add_media_part(media)   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\package.py", line 211, in get_or_add_media_part     media_part = self._find_by_sha1(media.sha1)   File "C:\Users\ajesh\AppData\Local\Programs\Python\Python36-32\lib\site-packages\pptx\package.py", line 224, in _find_by_sha1     if media_part.sha1 == sha1: AttributeError: 'Part' object has no attribute 'sha1'

Thanks, -Ajesh

scanny commented 6 years ago

Hmm, interesting. I think this is a result of the mp3 "file" ("part" in this context) not being loaded as a MediaPart object.

The mappings that control that are here: https://github.com/scanny/python-pptx/blob/master/pptx/__init__.py#L27

As you'll see, there's no entry for CT.MP3 or any other audio formats.

You can remedy that with this code, which must be run before you load your presentation:

from pptx.opc.package import PartFactory
from pptx.parts.media import MediaPart

PartFactory.part_type_for.update(
    {
        'audio/mp3': MediaPart
    }
)

The MIME-type ('audio/mp3' in this example) will need to exactly match the type attributed to your MP3 file in the [Content_Types].xml part of your template package (.pptx file).

I'm not sure if that will fix everything, but it should at least move you to the next error.

If you want to do the research and assemble the content types for audio files that PowerPoint supports I can add that into the next release. I've got one in the hopper here and should be publishing it in a few days.

ajeshp commented 6 years ago

Yes, that's all that was required. Thank You!! The MIME-type was 'audio/mpeg' in the [Content_Types].xml file, so used that. I will try to get you the content types for audio files that Powerpoint supports.

goldengrape commented 5 years ago

@scanny Could you please give an example of how to add an mp3 into a slide?

goldengrape commented 5 years ago
ppt_filename="data/test.pptx"
movie_file=["data/test/temp_000.mp3","data/test/temp_001.mp3"]
prs = Presentation(ppt_filename)
for index, slide in enumerate(prs.slides):
    notes_slide = slide.notes_slide
    shapes = slide.shapes
    movie = shapes.add_movie(movie_file[index], 
                   100, 100, 400, 400, 
                   poster_frame_image=None, 
                   mime_type='audio/mp3')

prs.save('data/test2.pptx')

It works. However, the sound clips are zero width and zero height in powerpoint. and, how can I make them autoplay?

goldengrape commented 5 years ago
ppt_filename="data/test.pptx"
movie_file=["data/test/temp_000.mp3","data/test/temp_001.mp3"]
prs = Presentation(ppt_filename)
left = top = width = height = Inches(1.0)

for index, slide in enumerate(prs.slides):
    notes_slide = slide.notes_slide
    shapes = slide.shapes
    movie = shapes.add_movie(movie_file[index], 
                             left , top , width , height, 
                             poster_frame_image=None, 
                             mime_type='video/unknown')

prs.save('data/test2.pptx')

I get it. the size must have an unit

ISabariRajan commented 1 year ago

@goldengrape : You helped a ton. I was looking for this answer all around.

navono commented 1 year ago

Any possible to set the movie shape auto run?