Skip to content

Commit 56c32ee

Browse files
authored
Merge pull request #60 from pozitronik/issue_59
Issue 59
2 parents 705dc03 + 94c349a commit 56c32ee

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,6 @@ Swap all faces on the `d:\videos\not_a_porn.mp4` video file to the face from `d:
8181
python sin.py --source="d:\pictures\any_picture.jpg" --target="d:\pictures\pngs_dir" --output="d:\pictures\pngs_dir\enhanced" --frame-processor=FaceEnhancer --many-faces --max-memory=24 --execution-provider=cuda --execution-threads=8
8282
```
8383
Enhance all faces in every PNG file in the `d:\pictures\pngs_dir` directory using the `cuda` provider and 8 simultaneous execution threads, with limit of 24 Gb RAM, and save every enhanced image to the `d:\pictures\pngs_dir\enhanced` directory.<br/>
84-
**Note 1**: only PNG images are supported at the moment.<br/>
85-
**Note 2**: even if the selected frame processor does not require a `source`, you should provide one at this time.
8684

8785
## Configuration file
8886

@@ -104,12 +102,24 @@ You also can pass path to the custom configuration file as a command line parame
104102
python sin.py --ini="d:\path\custom.ini"
105103
```
106104

105+
## How to handle output videos quality/encoding speed/etc?
106+
107+
In brief, sinner relies on the `ffmpeg` software almost every time video processing is required, and it's possible to utilize all the incredible powers of `ffmpeg`. Use the `--ffmpeg_resulting_parameters` key to control how `ffmpeg` will encode the output video: simply pass the usual `ffmpeg` parameters as the value for this key (remember not to forget enclosing the value string in commas). There are some examples:
108+
109+
* `--ffmpeg_resulting_parameters="-c:v libx264 -preset medium -crf 20 -pix_fmt yuv420p"`: use software x264 encoder (`-c:v libx264`) with the medium quality (`-preset medium` and `-crf 20`) and `yuv420p` pixel format. This is the default parameter value.
110+
* `--ffmpeg_resulting_parameters="-c:v h264_nvenc -preset slow -qp 20 -pix_fmt yuv420p"`: use nVidia GPU-accelerated x264 encoder (`-c:v h264_nvenc`) with the good encoding quality (`-preset slow` and `-qp 20`). This encoder is worth to use if it supported by your GPU.
111+
* `--ffmpeg_resulting_parameters="-c:v hevc_nvenc -preset slow -qp 20 -pix_fmt yuv420p"`: the same as above, but with x265 encoding.
112+
* `--ffmpeg_resulting_parameters="-c:v h264_amf -b:v 2M -pix_fmt yuv420p"`: the AMD hardware-accelerated x264 encoder (`-c:v h264_amf`) with 2mbps resulting video bitrate (-b:v 2M). This should be good for AMD GPUs.
113+
114+
And so on. As you can find, there are a lot of different presets and options for the every `ffmpeg` encoder, and you can rely on the [documentation](https://ffmpeg.org/ffmpeg-codecs.html) to achieve desired results.
115+
116+
In case, when `ffmpeg` is not available in your system, sinner will gracefully degrade to CV2 library possibilities. In that case all video processing features should work, but in a very basic way: only with the software x264 encoder, which is slow and thriftless.
117+
107118
## FAQ
108119

109120
:question: What are the differences between sinner and roop?<br/>
110121
:exclamation: As said before, sinner has started as a fork of roop. They share similar ideas, but they differ in the ways how those ideas should be implemented.
111-
sinner uses the same ML libraries to perform its magic, but handles them in its own way. From a developer's perspective, it has a better architecture (OOP instead of functional approach),
112-
stricter types handling and more comprehensive tests. From the point of view of a user, sinner offers additional features that Roop currently lacks.
122+
sinner uses the same ML libraries to perform its magic, but handles them in its own way. From a developer's perspective, it has a better architecture (OOP instead of functional approach), stricter types handling and more comprehensive tests. From the point of view of a user, sinner offers additional features that Roop currently lacks.
113123

114124
:question: Is there a NSWF filter?<br/>
115125
:exclamation: Nope. I don't care if you will do nasty things with sinner, it's your responsibility. And sinner is just a neutral tool, like a hammer or a knife, it is the responsibility of the user to decide how they want to use it.

sinner/handlers/frame/FFmpegVideoHandler.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class FFmpegVideoHandler(BaseFrameHandler):
1818
emoji: str = '🎥'
1919

2020
output_fps: float
21+
ffmpeg_resulting_parameters: str
2122

2223
def rules(self) -> Rules:
2324
return super().rules() + [
@@ -26,6 +27,11 @@ def rules(self) -> Rules:
2627
'default': lambda: self.fps,
2728
'help': 'FPS of resulting video'
2829
},
30+
{
31+
'parameter': ['ffmpeg_resulting_parameters'],
32+
'default': '-c:v libx264 -preset medium -crf 20 -pix_fmt yuv420p',
33+
'help': 'ffmpeg command-line part to adjust resulting video parameters'
34+
},
2935
{
3036
'module_help': 'The video processing module, based on ffmpeg'
3137
}
@@ -97,8 +103,9 @@ def result(self, from_dir: str, filename: str, audio_target: str | None = None)
97103
self.update_status(f"Resulting frames from {from_dir} to {filename} with {self.output_fps} FPS")
98104
filename_length = len(str(self.fc)) # a way to determine frame names length
99105
Path(os.path.dirname(filename)).mkdir(parents=True, exist_ok=True)
100-
command = ['-r', str(self.output_fps), '-i', os.path.join(from_dir, f'%0{filename_length}d.png'), '-c:v', 'h264_nvenc', '-preset', 'medium', '-qp', '18', '-pix_fmt', 'yuv420p', '-vf',
101-
'colorspace=bt709:iall=bt601-6-625:fast=1', filename]
106+
command = ['-framerate', str(self.output_fps), '-i', os.path.join(from_dir, f'%0{filename_length}d.png')]
107+
command.extend(self.ffmpeg_resulting_parameters.split(' '))
108+
command.extend(['-r', str(self.output_fps), filename])
102109
if audio_target:
103110
command.extend(['-i', audio_target, '-shortest'])
104111
return self.run(command)

0 commit comments

Comments
 (0)