add metadata embed task and callback

This commit is contained in:
Simon 2025-10-29 22:31:30 +07:00
parent 79d994e460
commit e1393fc67c
No known key found for this signature in database
GPG Key ID: 2C15AA5E89985DD4
5 changed files with 93 additions and 0 deletions

View File

@ -87,6 +87,13 @@ RESYNC_THUMBS: TaskItemConfig = {
"api_stop": False,
}
RESYNC_METADATA: TaskItemConfig = {
"title": "Sync Metadata to Media Files",
"group": "setting:thumbnailsync",
"api_start": True,
"api_stop": False,
}
INDEX_PLAYLISTS: TaskItemConfig = {
"title": "Index Channel Playlist",
"group": "channel:indexplaylist",
@ -119,6 +126,7 @@ TASK_CONFIG: dict[str, TaskItemConfig] = {
"rescan_filesystem": RESCAN_FILESYSTEM,
"thumbnail_check": THUMBNAIL_CHECK,
"resync_thumbs": RESYNC_THUMBS,
"resync_metadata": RESYNC_METADATA,
"index_playlists": INDEX_PLAYLISTS,
"subscribe_to": SUBSCRIBE_TO,
"version_check": VERSION_CHECK,

View File

@ -24,6 +24,7 @@ from download.src.yt_dlp_handler import VideoDownloader
from task.src.notify import Notifications
from task.src.task_config import TASK_CONFIG
from task.src.task_manager import TaskManager
from video.src.meta_embed import MetadataEmbed
class BaseTask(Task):
@ -302,6 +303,19 @@ def re_sync_thumbs(self):
ThumbFilesystem(task=self).embed()
@shared_task(bind=True, name="resync_metadata", base=BaseTask)
def re_sync_metadata(self):
"""resync metadata to media files"""
manager = TaskManager()
if manager.is_pending(self):
print(f"[task][{self.name}] metadata re-embed is already running")
self.send_progress(["Metadata re-embed is already running."])
return
manager.init(self)
MetadataEmbed(task=self).embed()
@shared_task(bind=True, name="subscribe_to", base=BaseTask)
def subscribe_to(self, url_str: str, expected_type: str | bool = False):
"""

View File

@ -0,0 +1,51 @@
"""bulk metadata embedding"""
from common.src.es_connect import ElasticWrap, IndexPaginate
from video.src.index import YoutubeVideo
class MetadataEmbed:
"""sync metadata to videos in bulk"""
INDEX_NAME = "ta_video"
def __init__(self, task=False):
self.task = task
def embed(self):
"""entry point"""
data = {
"query": {"match_all": {}},
"_source": ["youtube_id"],
}
paginate = IndexPaginate(
index_name=self.INDEX_NAME,
data=data,
size=200,
callback=MetadataEmbedCallback,
task=self.task,
total=self._get_total(),
)
_ = paginate.get_results()
def _get_total(self):
"""get total documents in index"""
path = f"{self.INDEX_NAME}/_count"
response, _ = ElasticWrap(path).get()
return response.get("count")
class MetadataEmbedCallback:
"""callback for metadata embed"""
def __init__(self, source, index_name, counter=0):
self.source = source
self.index_name = index_name
self.counter = counter
def run(self):
"""run embed"""
for video in self.source:
youtube_id = video["_source"]["youtube_id"]
YoutubeVideo(youtube_id).embed_metadata()

View File

@ -5,6 +5,7 @@ type TaskNamesType =
| 'update_subscribed'
| 'manual_import'
| 'resync_thumbs'
| 'resync_metadata'
| 'rescan_filesystem';
const updateTaskByName = async (taskName: TaskNamesType) => {

View File

@ -13,6 +13,7 @@ const SettingsActions = () => {
const [deletePending, setDeletePending] = useState(false);
const [processingImports, setProcessingImports] = useState(false);
const [reEmbed, setReEmbed] = useState(false);
const [reSyncMeta, setReSyncMeta] = useState(false);
const [backupStarted, setBackupStarted] = useState(false);
const [isRestoringBackup, setIsRestoringBackup] = useState(false);
const [reScanningFileSystem, setReScanningFileSystem] = useState(false);
@ -44,6 +45,7 @@ const SettingsActions = () => {
deletePending ||
processingImports ||
reEmbed ||
reSyncMeta ||
backupStarted ||
isRestoringBackup ||
reScanningFileSystem
@ -53,6 +55,7 @@ const SettingsActions = () => {
setDeletePending(false);
setProcessingImports(false);
setReEmbed(false);
setReSyncMeta(false);
setBackupStarted(false);
setIsRestoringBackup(false);
setReScanningFileSystem(false);
@ -104,6 +107,22 @@ const SettingsActions = () => {
)}
</div>
</div>
<div className="settings-group">
<h2>Embed metadata into media file</h2>
<p>Embed metadata into media files as mp4 tags.</p>
<div id="re-meta">
{reSyncMeta && <p>Processing video metadata</p>}
{!reSyncMeta && (
<Button
label="Start process"
onClick={async () => {
await updateTaskByName('resync_metadata');
setReSyncMeta(true);
}}
/>
)}
</div>
</div>
<div className="settings-group">
<h2>ZIP file index backup</h2>
<p>