Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/development'
Browse files Browse the repository at this point in the history
  • Loading branch information
Trekky12 committed Dec 2, 2023
2 parents 9f2f6c7 + af32690 commit 3b0f8e1
Show file tree
Hide file tree
Showing 12 changed files with 306 additions and 92 deletions.
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ kburns-slideshow allows the creation of video slideshows from images with kburns
## Prerequisites

kburns-slideshow is a python application and needs Python 3 installed.
The videos are generated with [FFmpeg](https://ffmpeg.org/) which is needed in Version 3 or 4.
The videos are generated with [FFmpeg](https://ffmpeg.org/) which is needed with the minimium Version 3.
FFprobe (comes with FFmpeg) is used to extract the duration, width and height of input videos.

To sync the slide changes to the background music the music onsets are extracted with [aubio](https://aubio.org/).
Expand All @@ -27,10 +27,10 @@ pip install -r requirements.txt
* when there should be only support for `wav` files
* download and extract [aubio 0.4.6](https://aubio.org/download) for windows ([win64](https://aubio.org/bin/0.4.6/aubio-0.4.6-win64.zip)/[win32](https://aubio.org/bin/0.4.6/aubio-0.4.6-win32.zip))
* when there should be a support for various audio files
* download [aubio 0.4.6 with ffmpeg](https://aubio.org/download) for windows ([win64](https://aubio.org/bin/0.4.6/aubio-0.4.6-win64-ffmpeg.zip)/[win32](https://aubio.org/bin/0.4.6/aubio-0.4.6-win32-ffmpeg.zip)) and the corresponding FFmpeg 3.3.3 shared build([win64](https://ffmpeg.zeranoe.com/builds/win64/shared/ffmpeg-3.3.3-win64-shared.zip)/[win32](https://ffmpeg.zeranoe.com/builds/win32/shared/ffmpeg-3.3.3-win32-shared.zip))
* download [aubio 0.4.6 with ffmpeg](https://aubio.org/download) for windows ([win64](https://aubio.org/bin/0.4.6/aubio-0.4.6-win64-ffmpeg.zip)/[win32](https://aubio.org/bin/0.4.6/aubio-0.4.6-win32-ffmpeg.zip)) and the corresponding FFmpeg 3.3.3 shared build([win64](https://archive.org/download/zeranoe/win64/shared/ffmpeg-3.3.3-win64-shared.zip)/[win32](https://archive.org/download/zeranoe/win32/shared/ffmpeg-3.3.3-win32-shared.zip))
* extract aubio and extract the ffmpeg shared dlls from the `bin` folder of ffmpeg to the `bin` folder of aubio
* download and extract [FFmpeg 4.2.1](https://ffmpeg.zeranoe.com/builds/)
* adjusts the paths to FFmpeg 4.2.1 (`bin/ffmpeg.exe`, `bin/ffprobe.exe`) and aubio (`bin/aubioonset.exe`) in `config.json`
* download and extract the latest version of [FFmpeg](https://www.gyan.dev/ffmpeg/builds/)
* adjusts the paths to FFmpeg (`bin/ffmpeg.exe`, `bin/ffprobe.exe`) and aubio (`bin/aubioonset.exe`) in `config.json`

#### Linux
* install Python3
Expand Down Expand Up @@ -106,11 +106,9 @@ $ python3 kbvs.py
## Notices
When using the overlay text you need to be aware of the font specific settings.

On Windows FFmpeg 3 is build with `--enable-libfontconfig` but unfortunately the default font directory is not recognized.
You either need to create a custom `fonts.conf`, which is described [here](https://ffmpeg.zeranoe.com/forum/viewtopic.php?f=7&t=2554#p8531)
or you can use the path to the font with the parameter `font_file`.
To use font names the FFmpeg build must be built with `--enable-libfontconfig`. This can be checked by calling `ffmpeg` and look for this attribute.

With FFmpeg 4 the default font directory is recognized and the parameter `font` can be used. The font file is then automatically found with the help of fontconfig.
Otherwise the full path to the font needs to be specified with the parameter `font_file`.

## Transitions
It is easy possible to create custom transitions. Just place a python file in the following format in the folder [transitions](/transitions):
Expand Down
3 changes: 3 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@
"zoom_direction_y": "random",
"zoom_direction_z": "random",
"scale_mode": "auto",
"pad_color": "#00000000",
"loopable": false,
"overwrite": false,
"generate_temp": false,
"delete_temp": false,
"temp_file_folder": "temp",
"temp_file_prefix": "temp-kburns-",
"output_temp_parameters": "-preset ultrafast -tune stillimage",
"output_temp_codec": "libx264",
"sync_to_audio": false,
"sync_titles_to_slides": false,
"save": false,
Expand Down
2 changes: 1 addition & 1 deletion docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ Additionally it is possible to add a text `overlay`:
"file": "1.jpg",
"overlay_text": {
"title": "Intro Text",
"font": "Bauhaus 93",
"font_file": "C:/Windows/Fonts/BAUHS93.TTF",
"font_size": 200,
"duration": 2,
"offset": 0,
Expand Down
4 changes: 2 additions & 2 deletions example.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"slide_duration": 5,
"overlay_text":{
"title": "Title 1",
"font": "Bauhaus 93",
"font_file": "C:/Windows/Fonts/BAUHS93.TTF",
"font_size": 200,
"duration": 2,
"transition_x": "left-to-center",
Expand All @@ -52,7 +52,7 @@
"file": "data\\2.mp4",
"overlay_text":{
"title": "Title 2",
"font": "Bauhaus 93",
"font_file": "C:/Windows/Fonts/BAUHS93.TTF",
"font_size": 200,
"duration": 2,
"transition_x": "center",
Expand Down
31 changes: 27 additions & 4 deletions gui/ConfigFrame.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
class ConfigFrame(tk.Toplevel):
def __init__(self, parent, **options):
super().__init__()

self.inputffmpeg = tk.StringVar()
self.inputffprobe = tk.StringVar()
self.inputAubio = tk.StringVar()
Expand All @@ -22,6 +22,8 @@ def __init__(self, parent, **options):
self.inputOverwrite = tk.BooleanVar()
self.inputGenerateTemp = tk.BooleanVar()
self.inputDeleteTemp = tk.BooleanVar()
self.inputOutputTempParameters = tk.StringVar()
self.inputOutputTempCodec = tk.StringVar()
self.inputSyncToAudio = tk.BooleanVar()

self.inputOutputWidth = tk.StringVar()
Expand All @@ -36,6 +38,7 @@ def __init__(self, parent, **options):
self.inputZoomDirectionY = tk.StringVar()
self.inputZoomDirectionZ = tk.StringVar()
self.inputScaleMode = tk.StringVar()
self.inputPadColor = tk.StringVar()

self.inputTransitionDuration = tk.StringVar()
self.inputTransition = tk.StringVar()
Expand All @@ -61,7 +64,7 @@ def create(self, config_path, choices):

scrollFrame = ScrollFrame(self, 200, True)
scrollFrame.grid(row=0, column=0, sticky=tk.NSEW)

configFrame = tk.Frame(scrollFrame.getCanvas())

pathFrame = tk.LabelFrame(configFrame, text="Paths")
Expand Down Expand Up @@ -163,6 +166,18 @@ def create(self, config_path, choices):
deleteTempCheckBox = tk.Checkbutton(tempFrame, var=self.inputDeleteTemp)
deleteTempCheckBox.grid(row=2, column=3, sticky=tk.W, padx=4, pady=4)

self.inputOutputTempParameters.set(self.config["output_temp_parameters"])
tempParametersLabel = tk.Label(tempFrame, text="Parameters")
tempParametersLabel.grid(row=3, column=0, sticky=tk.W, padx=4, pady=4)
tempParametersEntry = tk.Entry(tempFrame, width=67, textvariable=self.inputOutputTempParameters)
tempParametersEntry.grid(row=3, column=1, columnspan=3, sticky=tk.W, padx=4, pady=4)

self.inputOutputTempCodec.set(self.config["output_temp_codec"])
tempCodecLabel = tk.Label(tempFrame, text="Codec")
tempCodecLabel.grid(row=4, column=0, sticky=tk.W, padx=4, pady=4)
tempCodecEntry = tk.Entry(tempFrame, textvariable=self.inputOutputTempCodec)
tempCodecEntry.grid(row=4, column=1, sticky=tk.W, padx=4, pady=4)

slideFrame = tk.LabelFrame(configFrame, text="Image Slides")
slideFrame.grid(row=3, column=0, sticky=tk.NSEW, padx=4, pady=4)

Expand Down Expand Up @@ -211,6 +226,12 @@ def create(self, config_path, choices):
scaleModeCombo = ttk.Combobox(slideFrame, values=choices["scale_mode"], textvariable=self.inputScaleMode)
scaleModeCombo.grid(row=6, column=1, sticky=tk.W, padx=4, pady=4)

self.inputPadColor.set(self.config["pad_color"] if "pad_color" in self.config else "black")
padColorLabel = tk.Label(slideFrame, text="Padding Background Color")
padColorLabel.grid(row=7, column=0, sticky=tk.W, padx=4, pady=4)
padColorEntry = tk.Entry(slideFrame, textvariable=self.inputPadColor)
padColorEntry.grid(row=7, column=1, sticky=tk.W, padx=4, pady=4)

transitionFrame = tk.LabelFrame(configFrame, text="Transition")
transitionFrame.grid(row=7, column=0, sticky=tk.NSEW, padx=4, pady=4)

Expand Down Expand Up @@ -241,9 +262,8 @@ def create(self, config_path, choices):

buttonSaveSlide = tk.Button(configFrame, text="Save", command=(lambda: self.saveConfig()))
buttonSaveSlide.grid(row=8, column=0, sticky=tk.NW, padx=4, pady=4)

scrollFrame.addFrame(configFrame, tk.NW)


def getConfig(self):
return {
Expand All @@ -269,10 +289,13 @@ def getConfig(self):
"zoom_direction_y": self.inputZoomDirectionY.get(),
"zoom_direction_z": self.inputZoomDirectionZ.get(),
"scale_mode": self.inputScaleMode.get(),
"pad_color": self.inputPadColor.get(),
"loopable": self.inputLoopable.get(),
"overwrite": self.inputOverwrite.get(),
"generate_temp": self.inputGenerateTemp.get(),
"delete_temp": self.inputDeleteTemp.get(),
"output_temp_parameters": self.inputOutputTempParameters.get(),
"output_temp_codec": self.inputOutputTempCodec.get(),
"temp_file_folder": self.inputTempFileFolder.get(),
"temp_file_prefix": self.inputTempFilePrefix.get(),
"sync_to_audio": self.inputSyncToAudio.get()
Expand Down
36 changes: 30 additions & 6 deletions gui/SettingsFrame.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def __init__(self, parent, **options):
self.inputOverwrite = tk.BooleanVar()
self.inputGenerateTemp = tk.BooleanVar()
self.inputDeleteTemp = tk.BooleanVar()
self.inputOutputTempParameters = tk.StringVar()
self.inputOutputTempCodec = tk.StringVar()
self.inputSyncToAudio = tk.BooleanVar()

self.inputOutputWidth = tk.StringVar()
Expand All @@ -30,6 +32,7 @@ def __init__(self, parent, **options):
self.inputZoomDirectionY = tk.StringVar()
self.inputZoomDirectionZ = tk.StringVar()
self.inputScaleMode = tk.StringVar()
self.inputPadColor = tk.StringVar()

self.inputTransitionDuration = tk.StringVar()
self.inputTransition = tk.StringVar()
Expand All @@ -44,14 +47,14 @@ def __init__(self, parent, **options):
def create(self, slideshow_config, choices):

self.slideshow_config = slideshow_config

self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.geometry("700x700")

scrollFrame = ScrollFrame(self, 200, True)
scrollFrame.grid(row=0, column=0, sticky=tk.NSEW)

configFrame = tk.Frame(scrollFrame.getCanvas())

outputFrame = tk.LabelFrame(configFrame, text="Output")
Expand Down Expand Up @@ -105,7 +108,7 @@ def create(self, slideshow_config, choices):
syncToAudioCheckBox = tk.Checkbutton(outputFrame, var=self.inputSyncToAudio)
syncToAudioCheckBox.grid(row=6, column=1, sticky=tk.W, padx=4, pady=4)

tempFrame = tk.LabelFrame(configFrame, text="Temporary files")
tempFrame = tk.LabelFrame(configFrame, text="Temporary files")
tempFrame.grid(row=2, column=0, sticky=tk.NSEW, padx=4, pady=4)

self.inputTempFileFolder.set(slideshow_config["temp_file_folder"])
Expand All @@ -132,7 +135,19 @@ def create(self, slideshow_config, choices):
deleteTempCheckBox = tk.Checkbutton(tempFrame, var=self.inputDeleteTemp)
deleteTempCheckBox.grid(row=2, column=3, sticky=tk.W, padx=4, pady=4)

slideFrame = tk.LabelFrame(configFrame, text="Image Slides")
self.inputOutputTempParameters.set(self.slideshow_config["output_temp_parameters"])
tempParametersLabel = tk.Label(tempFrame, text="Parameters")
tempParametersLabel.grid(row=3, column=0, sticky=tk.W, padx=4, pady=4)
tempParametersEntry = tk.Entry(tempFrame, width=67, textvariable=self.inputOutputTempParameters)
tempParametersEntry.grid(row=3, column=1, columnspan=3, sticky=tk.W, padx=4, pady=4)

self.inputOutputTempCodec.set(self.slideshow_config["output_temp_codec"])
tempCodecLabel = tk.Label(tempFrame, text="Codec")
tempCodecLabel.grid(row=4, column=0, sticky=tk.W, padx=4, pady=4)
tempCodecEntry = tk.Entry(tempFrame, textvariable=self.inputOutputTempCodec)
tempCodecEntry.grid(row=4, column=1, sticky=tk.W, padx=4, pady=4)

slideFrame = tk.LabelFrame(configFrame, text="Image Slides")
slideFrame.grid(row=3, column=0, sticky=tk.NSEW, padx=4, pady=4)

self.inputDuration.set(slideshow_config["slide_duration"])
Expand Down Expand Up @@ -180,7 +195,13 @@ def create(self, slideshow_config, choices):
scaleModeCombo = ttk.Combobox(slideFrame, values=choices["scale_mode"], textvariable=self.inputScaleMode)
scaleModeCombo.grid(row=6, column=1, sticky=tk.W, padx=4, pady=4)

transitionFrame = tk.LabelFrame(configFrame, text="Transition")
self.inputPadColor.set(slideshow_config["pad_color"])
padColorLabel = tk.Label(slideFrame, text="Padding Background Color")
padColorLabel.grid(row=7, column=0, sticky=tk.W, padx=4, pady=4)
padColorEntry = tk.Entry(slideFrame, textvariable=self.inputPadColor)
padColorEntry.grid(row=7, column=1, sticky=tk.W, padx=4, pady=4)

transitionFrame = tk.LabelFrame(configFrame, text="Transition")
transitionFrame.grid(row=7, column=0, sticky=tk.NSEW, padx=4, pady=4)

self.inputTransitionDuration.set(slideshow_config["fade_duration"])
Expand All @@ -207,7 +228,7 @@ def create(self, slideshow_config, choices):
transitionCellsLabel.grid(row=3, column=0, sticky=tk.W, padx=4, pady=4)
transitionCellsEntry = tk.Entry(transitionFrame, textvariable=self.inputTransitionCells)
transitionCellsEntry.grid(row=3, column=1, sticky=tk.W, padx=4, pady=4)

scrollFrame.addFrame(configFrame, tk.NW)

def getConfig(self):
Expand All @@ -228,10 +249,13 @@ def getConfig(self):
"zoom_direction_y": self.inputZoomDirectionY.get(),
"zoom_direction_z": self.inputZoomDirectionZ.get(),
"scale_mode": self.inputScaleMode.get(),
"pad_color": self.inputPadColor.get(),
"loopable": self.inputLoopable.get(),
"overwrite": self.inputOverwrite.get(),
"generate_temp": self.inputGenerateTemp.get(),
"delete_temp": self.inputDeleteTemp.get(),
"output_temp_parameters": self.inputOutputTempParameters.get(),
"output_temp_codec": self.inputOutputTempCodec.get(),
"temp_file_folder": self.inputTempFileFolder.get(),
"temp_file_prefix": self.inputTempFilePrefix.get(),
"sync_to_audio": self.inputSyncToAudio.get()
Expand Down
Loading

0 comments on commit 3b0f8e1

Please sign in to comment.