Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request]: Automatic timestamping #677

Open
2 tasks done
dot-mike opened this issue Mar 9, 2024 · 1 comment
Open
2 tasks done

[Feature Request]: Automatic timestamping #677

dot-mike opened this issue Mar 9, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@dot-mike
Copy link
Contributor

dot-mike commented Mar 9, 2024

I've read the documentation

Your Feature Request

I would like comments to have clickable timestamps i.e if the text 12:13 is found in the comment it should be turned into a clickable link that would take me to the same timestamp in the videoplayer.

Your help is needed!

  • Yes I will work on this in the next few days or weeks.

Example implementation:

tubearchivist/api/views.py

diff --git a/tubearchivist/api/views.py b/tubearchivist/api/views.py
index e026dba..e1f8636 100644
--- a/tubearchivist/api/views.py
+++ b/tubearchivist/api/views.py
@@ -50,6 +50,11 @@ from rest_framework.authtoken.views import ObtainAuthToken
 from rest_framework.response import Response
 from rest_framework.views import APIView
 
+import re
+import logging
+import time
+
+logger = logging.getLogger('ta')
 
 def check_admin(user):
     """check for admin permission for restricted views"""
@@ -230,8 +235,39 @@ class VideoCommentView(ApiBaseView):
         # pylint: disable=unused-argument
         self.get_document(video_id)
 
+        # convert \n to <br> for comments and replies
+        data = self.response.get("data")
+        if isinstance(data, list):
+            comment_count = 0
+            start_time = time.time()  # Start the timer
+            for comment in data:
+                comment_count += 1
+                comment["comment_text"] = comment["comment_text"].replace("\n", "<br>")
+                comment["comment_text"] = self._add_seek_to(comment["comment_text"])
+                for reply in comment["comment_replies"]:
+                    comment_count += 1
+                    reply["comment_text"] = reply["comment_text"].replace("\n", "<br>")
+                    reply["comment_text"] = self._add_seek_to(reply["comment_text"])
+            end_time = time.time()  # End the timer
+            logger.debug("Time taken to parse %s comments: %s seconds", comment_count, (end_time - start_time))
+        else:
+            logger.warning("No comments found for video %s", video_id)
+
         return Response(self.response, status=self.status_code)
 
+    def _add_seek_to(self, comment_text):
+        """add js seekTo for timestamp in comments """
+
+        # Regular expression to match timestamps in the format of HH:MM:SS or MM:SS
+        timestamp_pattern = r"\b(?:[0-1]?[0-9]|2[0-3]):(?:[0-5]?[0-9]):(?:[0-5][0-9])|\b(?:[0-5]?[0-9]):(?:[0-5][0-9])\b"
+        timestamps = re.findall(timestamp_pattern, comment_text)
+
+        for timestamp in timestamps:
+            seek_to = f"javascript:seekVideoTo('{timestamp}')"
+            comment_text = comment_text.replace(timestamp, f'<a href="{seek_to}" class="ta-comment-timesamp>{timestamp}</a>')
+
+        return comment_text
+
 
 class VideoSimilarView(ApiBaseView):
     """resolves to /api/video/<video-id>/similar/

tubearchivist/static/script.js

diff --git a/tubearchivist/static/script.js b/tubearchivist/static/script.js
index b1e6ad1..2423fbb 100644
--- a/tubearchivist/static/script.js
+++ b/tubearchivist/static/script.js
@@ -1266,7 +1266,7 @@ function createCommentBox(comment, isRoot) {
   commentBox.appendChild(commentAuthor);
 
   let commentText = document.createElement('p');
-  commentText.innerText = comment.comment_text;
+  commentText.innerHTML = comment.comment_text;
   commentBox.appendChild(commentText);
 
   const spacer = '<span class="space-carrot">|</span>';
@@ -1567,3 +1567,21 @@ function doShortcut(e) {
     }
   }
 }
+
+function seekVideoTo(timestamp) {
+  let videoElement = getVideoPlayer();
+  if (videoElement != null) {
+    const parts = timestamp.split(':');
+    // HH:MM:SS and MM:SS
+    let seconds;
+    if (parts.length === 3) {
+      seconds = parseInt(parts[0]) * 3600 + parseInt(parts[1]) * 60 + parseInt(parts[2]);
+    } else {
+      seconds = parseInt(parts[0]) * 60 + parseInt(parts[1]);
+    }
+    videoElement.currentTime = seconds;
+
+    videoElement.scrollIntoView({ behavior: 'smooth' });
+  }
+}
+
@bbilly1
Copy link
Member

bbilly1 commented Mar 11, 2024

Would also be great if that can be handled in the description.

Ideally this shouldn't touch the index, as in things should be indexed as it is on YT, but links could be added dynamically when parsing the descriptions.

@bbilly1 bbilly1 added the enhancement New feature or request label Mar 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants