Repository: Zulko/moviepy

Issue:
RFE: Ability to chose path for temp file on write_videofile
I'm trying to use moviepy on a Google Cloud Function (similar do AWS Lambda) and can't get around this problem. Even though I can download the original movie and save the resized movie, in an specified directory, the operation fails because write_videofile creates a temp file wherever the code is running. On GCF's case it runs on a read-only fs, which makes the operation impossible.
The ability to chose where to store the temp file would be huge.


Discussion:
coveralls: 
[![Coverage Status](https://coveralls.io/builds/30072974/badge)](https://coveralls.io/builds/30072974)

Coverage increased (+0.3%) to 64.631% when pulling **90e85b2840cf3c8b7b92a623155061642ce02624 on tburrows13:set-tempfile-path** into **b606067833d95016937fb90732400d93ee5389e8 on Zulko:master**.

tburrows13: I'm ready for this to be merged.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7e789d1..b272ce2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,10 +15,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - If you were previously setting custom locations for FFmpeg or ImageMagick in ``config_defaults.py`` and MoviePy still cannot autodetect the binaries, you will need to switch to the new method using enviroment variables. [#1109]
 
 ### Added <!-- for new features -->
-- Support for path-like objects as an option wherever filenames are passed in as arguments
+- Support for path-like objects as an option wherever filenames are passed in as arguments [#1137]
 - Autodetect ImageMagick executable on Windows [#1109]
 - Optionally configure paths to FFmpeg and ImageMagick binaries with environment variables or a ``.env`` file [#1109]
 - Optional `encoding` parameter in `SubtitlesClip` [#1043]
+- Optional `temp_audiofile_path` parameter in `VideoClip.write_videofile()` to specify where the temporary audiofile should be created [#1144]
 
 ### Changed <!-- for changes in existing functionality -->
 
diff --git a/moviepy/video/VideoClip.py b/moviepy/video/VideoClip.py
index f9615b7..ab9b649 100644
--- a/moviepy/video/VideoClip.py
+++ b/moviepy/video/VideoClip.py
@@ -23,6 +23,7 @@ from moviepy.decorators import (
     outplace,
     requires_duration,
     use_clip_fps_by_default,
+    convert_path_to_string,
 )
 from moviepy.tools import extensions_dict, find_extension, subprocess_call
 from moviepy.video.io.ffmpeg_writer import ffmpeg_write_video
@@ -139,7 +140,7 @@ class VideoClip(Clip):
     @requires_duration
     @use_clip_fps_by_default
     @convert_masks_to_RGB
-    @convert_path_to_string("filename")
+    @convert_path_to_string(["filename", "temp_audiofile", "temp_audiofile_path"])
     def write_videofile(
         self,
         filename,
@@ -154,6 +155,7 @@ class VideoClip(Clip):
         audio_bitrate=None,
         audio_bufsize=2000,
         temp_audiofile=None,
+        temp_audiofile_path="",
         rewrite_audio=True,
         remove_temp=True,
         write_logfile=False,
@@ -216,12 +218,16 @@ class VideoClip(Clip):
           If ``audio`` is the name of an audio file, this audio file
           will be incorporated as a soundtrack in the movie.
 
-        audiofps
+        audio_fps
           frame rate to use when generating the sound.
 
         temp_audiofile
-          the name of the temporary audiofile to be generated and
-          incorporated in the the movie, if any.
+          the name of the temporary audiofile, as a string or path-like object, to be created and
+          then used to write the complete video, if any.
+
+        temp_audiofile_path
+          the location that the temporary audiofile is placed, as a
+          string or path-like object. Defaults to the current working directory.
 
         audio_codec
           Which audio codec should be used. Examples are 'libmp3lame'
@@ -304,7 +310,10 @@ class VideoClip(Clip):
             audiofile = temp_audiofile
         elif make_audio:
             audio_ext = find_extension(audio_codec)
-            audiofile = name + Clip._TEMP_FILES_PREFIX + "wvf_snd.%s" % audio_ext
+            audiofile = os.path.join(
+                temp_audiofile_path,
+                name + Clip._TEMP_FILES_PREFIX + "wvf_snd.%s" % audio_ext,
+            )
 
         # enough cpu for multiprocessing ? USELESS RIGHT NOW, WILL COME AGAIN
         # enough_cpu = (multiprocessing.cpu_count() > 1)


Test patch:
diff --git a/tests/test_VideoClip.py b/tests/test_VideoClip.py
index 21d681d..99ad4a6 100644
--- a/tests/test_VideoClip.py
+++ b/tests/test_VideoClip.py
@@ -37,6 +37,18 @@ def test_errors_with_redirected_logs():
     close_all_clips(locals())
 
 
+def test_write_videofiles_with_temp_audiofile_path():
+    clip = VideoFileClip("media/big_buck_bunny_432_433.webm").subclip(0.2, 0.5)
+    location = os.path.join(TMP_DIR, "temp_audiofile_path.webm")
+    temp_location = "temp_audiofile"
+    if not os.path.exists(temp_location):
+        os.mkdir(temp_location)
+    clip.write_videofile(location, temp_audiofile_path=temp_location, remove_temp=False)
+    assert os.path.isfile(location)
+    contents_of_temp_dir = os.listdir(temp_location)
+    assert any(file.startswith("temp_audiofile_path") for file in contents_of_temp_dir)
+
+
 def test_save_frame():
     clip = VideoFileClip("media/big_buck_bunny_432_433.webm")
     location = os.path.join(TMP_DIR, "save_frame.png")
@@ -163,4 +175,5 @@ def test_withoutaudio():
 
 
 if __name__ == "__main__":
-    pytest.main()
+    # pytest.main()
+    test_write_videofiles_with_temp_audiofile_path()