Tdarr
Tdarr copied to clipboard
GPU doing CPU tasks, and vice versa
I just converted over to flows today. I'm having it rescan and attempt to convert files that had failed before. One thing I have noticed is that my GPU is doing all of the normal CPU tasks. And a current transcode that should be NVENC is being converted using the CPU. In the node options I do NOT have "Allow GPU workers to do CPU tasks" enabled, yet it's still doing them. Tasks such as reordering streams, cleaning audio, cleaning subtitles, etc.
My current flow: https://imgur.com/4sQU2GX
Node status: https://imgur.com/ZZOga23
Showing that it's doing the NVENC using the CPU: https://imgur.com/buQ4K2t
Copy of the log for a file transcoding on the CPU: https://hastebin.com/share/kucaretidu.swift
Any guidance as to what I have set up wrong here?
- OS: Unraid (docker)
- Browser: Chrome
- Version 2.17.01
After doing a little bit of research, it's acting like there is no worker designation for flows like there is for plugins. It just grabs the first available worker and runs. Is that correct?
Yes that's right, with flows it's the idea that there's logic in the flow that will give a CPU worker CPU related transcode args and a GPU worker GPU transcode related args. For example using the 'Encode Video' plugin has logic within it to do this. The classic plugins do not have this logic so might be the case that a CPU worker runs GPU args or vice versa. You can use the Check Node Hardware Encoder
flow plugin so that when GPU hardware is available it will do GPU transcoding. Can also use the Check Flow Variable
to check the worker type and act accordingly.
Yes that's right, with flows it's the idea that there's logic in the flow that will give a CPU worker CPU related transcode args and a GPU worker GPU transcode related args. For example using the 'Encode Video' plugin has logic within it to do this. The classic plugins do not have this logic so might be the case that a CPU worker runs GPU args or vice versa. You can use the
Check Node Hardware Encoder
flow plugin so that when GPU hardware is available it will do GPU transcoding. Can also use theCheck Flow Variable
to check the worker type and act accordingly.
I'm not sure I'm following. When I use classic plugins, they are correctly using gpu and cpu workers. The cpu workers will do audio cleaning, subtitle cleaning, etc. And the gpu will only do transcoding. But when I set up the flows, no matter what I tried cpu and gpu would both do the same tasks. Cpu would be transcoding, even tho it was specified to be NVENC. And gpu would be doing subtitle and audio cleaning. It was just grabbing whatever worker was available, not caring about whether it was cpu or gpu.
I will look into the check node hardware encoder stuff when I get a chance. Could you elaborate on it?
The classic plugins do not have this logic
i believe it depends if the plugin autor took care and implemented this part.
take my classic plugin below, for example. It will check if there is GPU available and if its a GPU worker and set the ffmpeg parameters accordingly.
if its a CPU worker, it will not fail; will just fallback to transcode using CPU parameters, automagically.
https://github.com/yodog/tdarr/blob/main/Tdarr_Plugin_yodog_scale_and_transcode.js
"if its a CPU worker, it will not fail; will just fallback to transcode using CPU parameters, automagically." which isnt ideal... it should wait?
Question is, does this matter speed wise? If its a significant performance improvement, then it would be cool if tdarr would send requests to CPU/GPU depending on the work to do. If there is no worker free, it needs to wait. (maybe a condition with expected runtime could be implemented...)
@CurlyFlow yes that will be added soon, the system is mostly in place under the hood already.
@my95z34
This is what I'd do:
So first we check the workerType
, and if it's transcodecpu
worker we do CPU transcoding with classic plugin, if not then we double check that the node is able to do nvenc transcoding and if so then do GPU transcoding (other worker type is called transcodegpu
FYI).
You can copy and import this flow to try it, I will add it to the flow templates:
{
"name": "Dynamic Classic",
"description": "Dynamic Classic",
"tags": "",
"flowPlugins": [
{
"name": "Input File",
"sourceRepo": "Community",
"pluginName": "inputFile",
"version": "1.0.0",
"id": "7a6heYJTK",
"position": {
"x": 619.59375,
"y": 71
}
},
{
"name": "Check Flow Variable Worker Type",
"sourceRepo": "Community",
"pluginName": "checkFlowVariable",
"version": "1.0.0",
"id": "Xmz-M1Kcp",
"position": {
"x": 619.365588981588,
"y": 198.5575740188268
},
"inputsDB": {
"variable": "{{{args.workerType}}}",
"value": "transcodecpu"
}
},
{
"name": "Run Classic Transcode Plugin GPU",
"sourceRepo": "Community",
"pluginName": "runClassicTranscodePlugin",
"version": "1.0.0",
"id": "eqw2BDcZn",
"position": {
"x": 744.2234764236456,
"y": 576.0927759290009
}
},
{
"name": "Run Classic Transcode Plugin CPU",
"sourceRepo": "Community",
"pluginName": "runClassicTranscodePlugin",
"version": "1.0.0",
"id": "UINSF-Jto",
"position": {
"x": 404.7683242434599,
"y": 599.739336347842
},
"inputsDB": {
"pluginSourceId": "Community:Tdarr_Plugin_MC93_Migz1FFMPEG_CPU"
}
},
{
"name": "Check Node Hardware Encoder",
"sourceRepo": "Community",
"pluginName": "checkNodeHardwareEncoder",
"version": "1.0.0",
"id": "kgwN6R1_i",
"position": {
"x": 769.900492466526,
"y": 348.6591157806557
}
},
{
"name": "Replace Original File",
"sourceRepo": "Community",
"pluginName": "replaceOriginalFile",
"version": "1.0.0",
"id": "lxwMPh0uu",
"position": {
"x": 624.1582866864101,
"y": 833.8283054574069
}
},
{
"name": "Require Review",
"sourceRepo": "Community",
"pluginName": "requireReview",
"version": "1.0.0",
"id": "SWsh_Z7oE",
"position": {
"x": 624.1582866864101,
"y": 754.5681189626113
}
}
],
"flowEdges": [
{
"source": "7a6heYJTK",
"sourceHandle": "1",
"target": "Xmz-M1Kcp",
"targetHandle": null,
"id": "9qpseUiC8"
},
{
"source": "Xmz-M1Kcp",
"sourceHandle": "1",
"target": "UINSF-Jto",
"targetHandle": null,
"id": "uidvJfV-Y"
},
{
"source": "Xmz-M1Kcp",
"sourceHandle": "2",
"target": "kgwN6R1_i",
"targetHandle": null,
"id": "BjUAnQVoT"
},
{
"source": "kgwN6R1_i",
"sourceHandle": "1",
"target": "eqw2BDcZn",
"targetHandle": null,
"id": "6naXep3GD"
},
{
"source": "kgwN6R1_i",
"sourceHandle": "2",
"target": "UINSF-Jto",
"targetHandle": null,
"id": "MVgJ6Jw8v"
},
{
"source": "UINSF-Jto",
"sourceHandle": "1",
"target": "SWsh_Z7oE",
"targetHandle": null,
"id": "IybAjMLOh"
},
{
"source": "eqw2BDcZn",
"sourceHandle": "1",
"target": "SWsh_Z7oE",
"targetHandle": null,
"id": "Ye3W2wE5Y"
},
{
"source": "SWsh_Z7oE",
"sourceHandle": "1",
"target": "lxwMPh0uu",
"targetHandle": null,
"id": "HSogWrrs9"
}
]
}
This template has been added:
Let me know if you need any more help.
@HaveAGitGat I appreciate that. Just out of curiosity, how would I arrange that flow so that it would try to convert the video using NVENC, and if it fails, then try CPU, and if that fails, then just fail? I'm having a mental block....
as far as i see he posted a flow already... (but didnt i tried)
as far as i see he posted a flow already... (but didnt i tried)
The one that was just posted? As far as I can tell, from my limited experience with flows, all that is doing is checking the worker type that is available and then transcoding using that worker. There is no failure plan.
@my95z34 you try the gpu transcode and then connect the error handle to the cpu plugin:
Flow Example
{ "name": "Basic HEVC Video Flow", "description": "Basic HEVC Video Flow", "tags": "", "flowPlugins": [ { "name": "Input File", "sourceRepo": "Community", "pluginName": "inputFile", "version": "1.0.0", "id": "pE6rU7gkW", "position": { "x": 758.5809635618224, "y": 117.19206188888086 } }, { "name": "Check if hevc", "sourceRepo": "Community", "pluginName": "checkVideoCodec", "version": "1.0.0", "id": "91b7IrsEc", "position": { "x": 672.4549563302081, "y": 253.11148102973914 } }, { "name": "Replace Original File", "sourceRepo": "Community", "pluginName": "replaceOriginalFile", "version": "1.0.0", "id": "4fkfOyR3l", "position": { "x": 820.4549563302082, "y": 742.2114810297393 } }, { "name": "Run Classic Transcode Plugin GPU", "sourceRepo": "Community", "pluginName": "runClassicTranscodePlugin", "version": "1.0.0", "id": "cyhNCt1ih", "position": { "x": 386.9480559951306, "y": 423.3493807189681 } }, { "name": "Run Classic Transcode Plugin CPU", "sourceRepo": "Community", "pluginName": "runClassicTranscodePlugin", "version": "1.0.0", "id": "wtmaZzr3E", "position": { "x": 545.0613029173174, "y": 518.1139988993492 }, "inputsDB": { "pluginSourceId": "Community:Tdarr_Plugin_MC93_Migz1FFMPEG_CPU" } } ], "flowEdges": [ { "source": "pE6rU7gkW", "sourceHandle": "1", "target": "91b7IrsEc", "targetHandle": null, "id": "HhF4rw2DZ" }, { "source": "91b7IrsEc", "sourceHandle": "1", "target": "4fkfOyR3l", "targetHandle": null, "id": "W2nVG7ts5" }, { "source": "91b7IrsEc", "sourceHandle": "2", "target": "cyhNCt1ih", "targetHandle": null, "id": "ZWX9rMuJZ" }, { "source": "cyhNCt1ih", "sourceHandle": "1", "target": "4fkfOyR3l", "targetHandle": null, "id": "hLYGZziuF" }, { "source": "cyhNCt1ih", "sourceHandle": "err1", "target": "wtmaZzr3E", "targetHandle": null, "id": "HpKUPIW52" }, { "source": "wtmaZzr3E", "sourceHandle": "1", "target": "4fkfOyR3l", "targetHandle": null, "id": "FfJSMv1Je" } ] }
@HaveAGitGat Using the flow you just shared, I'm still getting the weirdness where CPU is running the GPU transcode, and vice versa.
@HaveAGitGat Using the flow you just shared, I'm still getting the weirdness where CPU is running the GPU transcode, and vice versa.
![]()
Although, looking at the FPS, maybe it is using the GPU even though it says CPU, and whatnot. I'm so damn confused, lol
The flow in my last message is not for CPU/GPU worker differentiation, it was for your question of how to attempt a GPU transcode and then if that fails fallback to CPU transcoding. You need to use the flow further up for CPU/GPU worker differentiation where the flow is checking the worker type at the beginning. You can combine both flows.
The flow in my last message is not for CPU/GPU worker differentiation, it was for your question of how to attempt a GPU transcode and then if that fails fallback to CPU transcoding. You need to use the flow further up for CPU/GPU worker differentiation where the flow is checking the worker type at the beginning. You can combine both flows.
Oh, gotcha.
Well, I'm sorry to be so needy, but could you help me with that part? I guess I don't understand where the worker check would go, in relation to the failure line. I'm sorry! 🤦🏼♂️
I guess my difficulty in understanding comes with how each step is performed. Does one worker go down each step until completion, or does the flow evaluate each step individually and assign, potentially, a different worker at each step?