-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from JaimeFlorian27/multiplatform
feat: removed findstr dependency, added linux and mac support.
- Loading branch information
Showing
9 changed files
with
171 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,9 @@ __pycache__/ | |
.Python | ||
build/ | ||
bin/ | ||
bin_linux/ | ||
bin_mac/ | ||
bin_windows/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,45 @@ | ||
# Reference Importer | ||
## Description | ||
Script that automates the importing of video reference into Maya, automatically creating an image sequence from a video file and creating an image plane with the sequence. | ||
# Installation | ||
## 1. Download the correct version from the Releases tab | ||
>If Using Maya 2021 or under, download ***ReferenceImporter.zip***. | ||
>If Using Maya 2022 or higher, download ***ReferenceImporter_Python3.zip***. | ||
## 2. Copy the contents of the zip to you Maya scripts folder | ||
>found under 'Documents/maya/***InsertMayaVerion***/scripts' | ||
## 2. Run the following command in Maya | ||
import reference_importer | ||
reference_importer.run() | ||
make sure to run it using Python | ||
|
||
# Usage | ||
|
||
## for a demonstration of usage please watch the video : | ||
|
||
[![Script Walkthrough Video](https://img.youtube.com/vi/ObX9NU2BmZo/0.jpg)](https://www.youtube.com/watch?v=ObX9NU2BmZo "Script Walkthrough Video") | ||
### 1. Choose a video file | ||
### 2. Set the desired trimming | ||
> Use format HH:MM:SS.ms for the timecode | ||
### 3. Set output sequence name and format | ||
### 4. Set output directory for the sequence | ||
### 5. (Optional) auto creation of image plane in Maya for the sequence | ||
### 6. Import the video!! | ||
Tool to help artists import videos as image sequence in Maya without going through a | ||
video editing package. Supports multiple file formats, length trimming and specifying a | ||
target frame rate. | ||
|
||
## Features | ||
- Video to image sequence conversion, for improved Reference Plane performance. | ||
- Automatic frame rate conversion (Forget about using Premiere Pro to change the frame rate of your reference!). | ||
- Automatic creation of a Reference Plane in Maya. | ||
- Multiplatform support (Windows, Mac and Linux). | ||
- [Ffmpeg](https://ffmpeg.org/) as the backend engine for video conversion. | ||
- [Qt.py](https://github.com/mottosso/Qt.py) abstraction for multiple Maya versions support (2022+). | ||
|
||
## Installation | ||
1. Find the latest version under the [Releases](https://github.com/JaimeFlorian27/reference-importer/releases) section. | ||
2. Download the right distribution for your platform. | ||
- Distributions use the following naming pattern: `reference_importer_<version>_<platform>.zip` | ||
3. Extract the zip file as a folder named `reference_importer` in your `$MAYA_APP_DIR/<MAYA_VERSION>/scripts` folder. | ||
- ie: `/home/jaime/Maya/2024/scripts/reference_importer` | ||
- [What is my MAYA_APP_DIR?](https://help.autodesk.com/view/MAYAUL/2024/ENU/?guid=GUID-228CCA33-4AFE-4380-8C3D-18D23F7EAC72) | ||
|
||
## Usage | ||
|
||
To launch Reference Importer, run the following Python script: | ||
``` | ||
import reference_importer | ||
reference_importer.run() | ||
``` | ||
|
||
### Workflow | ||
|
||
1. Select a video file in the UI. | ||
2. Set the desired start and end timecode. | ||
- End timecode will be populated by default to the end of the video. | ||
> Use HH:MM:SS.ms as the timecode format. | ||
3. Set output image sequence name. | ||
4. Set the output format. | ||
4. Select the output directory for the sequence. | ||
4. Set the desired target frame rate. | ||
5. (Optional) Enable creation of an Image Plane in Maya for the sequence. | ||
6. Import the video! | ||
|
||
#### Demonstration Video: | ||
|
||
[![Reference Importer demonstration video](https://img.youtube.com/vi/ObX9NU2BmZo/0.jpg)](https://www.youtube.com/watch?v=ObX9NU2BmZo "Script Walkthrough Video") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
from __future__ import annotations | ||
import re | ||
import shutil | ||
import subprocess | ||
import platform | ||
from pathlib import Path | ||
|
||
TIMECODE_REGEX = r"Duration: (\d{2}:\d{2}:\d{2}.\d)" | ||
|
||
|
||
class FfmpegError(Exception): | ||
... | ||
|
||
class MissingFfmpeg(FfmpegError): | ||
... | ||
|
||
|
||
class ImageSequencer: | ||
def __init__( | ||
self, | ||
video_file: str = "", | ||
output_name: str = "", | ||
padding: str = "%03d", | ||
output_frame_rate: int = 24, | ||
) -> None: | ||
self.output_frame_rate = output_frame_rate | ||
self.video_file = video_file | ||
self.output_name = output_name | ||
self.padding = padding | ||
self.trim_start = 0 | ||
self.trim_end = 0 | ||
self.ffmpeg_path = self.get_ffmpeg_path() | ||
|
||
@classmethod | ||
def get_ffmpeg_path(cls) -> Path: | ||
"""Resolves the path to ffmpeg. | ||
The script first attempts to use the ffmpeg available in the bin folder, | ||
otherwise it fallbacks to the first match of ffmpeg avaiable in Path. | ||
Raises: | ||
MissingFfmpeg: If no ffmpeg binaries are available. | ||
""" | ||
_ffmpeg_binary = f"ffmpeg{'.exe' if platform.system() == 'Windows' else ''}" | ||
ffmpeg_executable = Path(__file__).parent.parent.resolve() / "bin" / _ffmpeg_binary | ||
if not ffmpeg_executable.exists(): | ||
ffmpeg_executable = shutil.which("ffmpeg") | ||
|
||
if not ffmpeg_executable: | ||
raise MissingFfmpeg() | ||
return Path(ffmpeg_executable) | ||
|
||
def get_duration(self, video_file: str) -> str: | ||
"""Gets the duration of the video from the output of ffmpeg -i. | ||
Args: | ||
video_file: Video file. | ||
Raises: | ||
FfmpegError: If ffmpeg errors out and does not yield an output. | ||
ValueError: If there is no match for the duration in ffmpeg's output. | ||
Returns: | ||
Duration of the video in timecode. | ||
""" | ||
command = f'"{self.ffmpeg_path}" -i "{video_file}"' | ||
try: | ||
output = str( | ||
subprocess.run( | ||
command, | ||
shell=True, | ||
stderr=subprocess.STDOUT, | ||
stdout=subprocess.PIPE, | ||
check=False, | ||
), | ||
) | ||
|
||
except subprocess.CalledProcessError as e: | ||
_except_msg: str = "Unable to get ffmpeg output" | ||
raise FfmpegError(_except_msg) from e | ||
|
||
# re.search searches across the whole string (multiline output). | ||
match: re.Match | None = re.search(TIMECODE_REGEX, output) | ||
|
||
if not match: | ||
_except_msg: str = f"Unable to find Duration for video {video_file}" | ||
raise ValueError(_except_msg) | ||
|
||
# the timecode is the first group of the match. | ||
duration: str = str(match.groups(0)[0]) | ||
return duration | ||
|
||
def create_sequence( | ||
self, | ||
input_file: str, | ||
frame_rate: int, | ||
start_trim: str, | ||
end_trim: str, | ||
output_file: str, | ||
): | ||
command = ( | ||
f'"{self.ffmpeg_path}" -i "{input_file}" -r {frame_rate}' | ||
f" -vf scale=1280:-1 -q:v 3 -ss {start_trim} -to {end_trim} " | ||
f'"{output_file}"' | ||
) | ||
try: | ||
subprocess.run(command, shell=True, check=False) | ||
except subprocess.CalledProcessError as e: | ||
raise FfmpegError from e | ||
|
||
|
||
if __name__ == "__main__": | ||
pass |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.