Skip to content

Commit

Permalink
Refactor plugin to support JSONata queries of the FFprobe data
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh5 committed Feb 24, 2023
1 parent b3b894c commit 2fe0ea5
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 20 deletions.
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@

**<span style="color:#56adda">0.0.2</span>**
- Refactor plugin to support JSONata queries of the FFprobe data

**<span style="color:#56adda">0.0.1</span>**
- Initial version
66 changes: 66 additions & 0 deletions description.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,69 @@ Only files with matching FFprobe field values will be further processed by the f
- [Support](https://unmanic.app/discord)
- [Issues/Feature Requests](https://github.com/Unmanic/plugin.limit_library_search_by_ffprobe_data/issues)
- [Pull Requests](https://github.com/Unmanic/plugin.limit_library_search_by_ffprobe_data/pulls)

---

##### Documentation:

For information on formulating JSONata queries:
- [JSONata Documentation](https://docs.jsonata.org/overview.html)
- [JSONata Exerciser Tool](https://try.jsonata.org/pdNmg6BId)

---

##### Additional Information:

Try the **JSONata Exerciser Tool** listed in the Documentation above.

###### Examples:

Find all streams matching codec_name field of "h264".

- **The FFprobe field to match against**
```
$.streams[*].codec_name
```
- **Search strings**
```
h264
```
Find all subtitle streams matching codec_name field of "subrip".
- **The FFprobe field to match against**
```
$.streams[codec_type="subtitle"].codec_name
```
- **Search strings**
```
subrip
```
Find all video streams matching codec_name field of "hevc" or "h264" if the video stream is greater than 1000px but smaller than 2000px (1080p).
- **The FFprobe field to match against**
```
[$.streams[codec_type="video" and (coded_height > 1000) and (coded_height < 2000)].codec_name]
```
- **Search strings**
```
hevc,h264
```
Find files with a duration greater than 5 minutes.
- **The FFprobe field to match against**
```
[$.format.duration > 300 ? "true" : "false"]
```
- **Search strings**
```
true
```
:::warning
**Quotes**
The Python library used to parse the JSONata query does not support single quotes. Always use double quotes in your query as in the examples above.
:::
2 changes: 1 addition & 1 deletion info.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
"on_library_management_file_test": 0
},
"tags": "audio,video,ffmpeg",
"version": "0.0.1"
"version": "0.0.2"
}
47 changes: 28 additions & 19 deletions plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,9 @@
If not, see <https://www.gnu.org/licenses/>.
"""

import logging
import pprint
import json
import logging
import jsonata

from unmanic.libs.unplugins.settings import PluginSettings

Expand All @@ -41,13 +40,13 @@ class Settings(PluginSettings):
"add_all_matching_values": False,
}
form_settings = {
"stream_field": {
"stream_field": {
"label": "The FFprobe field to match against",
"description": "The name of the FFprobe field to match against with the search strings below."
"description": "A JSONata query to match name of the FFprobe field to match against with the search strings below."
},
"allowed_values": {
"label": "Search strings",
"description": "A comma separated list of strings to match in the stipulated FFprobe field above."
"description": "A comma separated list of strings to match agianst the JSONata query results."
},
"add_all_matching_values": {
"label": "Add all matching files to pending tasks list",
Expand All @@ -61,7 +60,7 @@ def __init__(self, *args, **kwargs):
super(Settings, self).__init__(*args, **kwargs)


def file_ends_in_allowed_values(probe_info, allowed_values):
def file_ends_in_allowed_values(probe_info, stream_field, allowed_values):
"""
Check if the file's video codec is in the list of values being searched for
Expand All @@ -78,19 +77,28 @@ def file_ends_in_allowed_values(probe_info, allowed_values):
if not file_probe_streams:
return False

# Loop over all streams found in the file probe
for stream_info in file_probe_streams:
codec_type = stream_info.get('codec_type', '').lower()
# If this is a video/image stream?
if codec_type == "video":
codec_name = stream_info.get('codec_name', '').lower()
logger.debug("File '%s' contains video codec '%s'.", file_path, codec_name)
# Check if it ends with one of the allowed_values
if codec_name and codec_name in allowed_values.split(','):
# If the config is empty (not yet configured) ignore everything
if not allowed_values:
logger.debug("Plugin has not yet been configured with allowed values. Blocking everything.")
return False

try:
context = jsonata.Context()
discovered_values = context(stream_field, probe_info)
except ValueError as e:
logger.debug("Failed to match the JSONata query to in the FFprobe data of the file '%s'.", file_path)
#logger.debug("Exception:", exc_info=e)
return False

for allowed_value in allowed_values.split(','):
# Ignore empty values (if plugin is configured with a trailing ','
if allowed_value:
if allowed_value in discovered_values:
logger.debug("File '%s' contains one of the configured values '%s'.", file_path, allowed_value)
return True

# File is not in the allowed video values
logger.debug("File '%s' does not contain one of the specified video values '%s'.", file_path, allowed_values)
logger.debug("File '%s' does not contain one of the specified values '%s'.", file_path, allowed_values)
return False


Expand Down Expand Up @@ -118,15 +126,16 @@ def on_library_management_file_test(data):
abspath = data.get('path')

# Get file probe
probe = Probe.init_probe(data, logger, allowed_mimetypes=['video'])
probe = Probe.init_probe(data, logger, allowed_mimetypes=['audio', 'video'])
if not probe:
# File not able to be probed by ffprobe
return

# Get the list of configured values to search for
stream_field = settings.get_setting('stream_field')
allowed_values = settings.get_setting('allowed_values')

in_allowed_values = file_ends_in_allowed_values(probe.get_probe(), allowed_values)
in_allowed_values = file_ends_in_allowed_values(probe.get_probe(), stream_field, allowed_values)
if not in_allowed_values:
# Ignore this file
data['add_file_to_pending_tasks'] = False
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jsonata==0.2.4

0 comments on commit 2fe0ea5

Please sign in to comment.