6.5 KiB
bitvid: Enhanced Video Comment System Specification
Objective
To implement a decentralized comment system for videos shared on a Nostr-based platform, combining multiple NIPs to provide structured, interactive, and scalable functionality for video comments, reactions, live discussions, and metadata tagging.
Features
-
Post Comments:
- Users can post comments on videos.
- Comments are associated with a specific video event using the
e
tag.
-
Structured Threading:
- Comments support threading by referencing parent comments using NIP-27 conventions.
- Threaded replies are visually nested.
-
Reactions:
- Users can react to comments (e.g., upvote, downvote) using NIP-25.
-
Live Discussions:
- Real-time public chat using NIP-28 for live video events.
-
Optional Metadata:
- Extra metadata fields are included for user preferences or administrative tags using NIP-24.
-
Real-Time Updates:
- Comments, reactions, and live chats update in real-time using Nostr subscriptions.
-
Moderation:
- Support for flagging or hiding inappropriate comments.
-
Privacy:
- Encrypted comments for private videos (optional).
Technical Specifications
1. Event Structure
Each component (comments, reactions, live chat) is represented as a Nostr event.
Comment Event:
{
"kind": 1311,
"pubkey": "abcdef1234567890...",
"created_at": 1675000000,
"tags": [
["e", "video-event-id"], // Reference to the video
["e", "parent-comment-id"], // Reference to the parent comment (optional, for replies)
["p", "commenter-pubkey"] // Optional: commenter pubkey
],
"content": "This is a great video!"
}
Reaction Event:
{
"kind": 7,
"pubkey": "abcdef1234567890...",
"created_at": 1675000000,
"tags": [
["e", "comment-event-id"], // Reference to the comment being reacted to
["p", "reactor-pubkey"]
],
"content": "+" // + for upvote, - for downvote
}
Live Chat Event:
{
"kind": 42,
"pubkey": "abcdef1234567890...",
"created_at": 1675000000,
"tags": [
["e", "video-event-id"], // Reference to the live video
["p", "participant-pubkey"]
],
"content": "What a great discussion!"
}
Metadata (Optional):
Metadata tags are added to comments or live chat events as needed:
{
"kind": 1311,
"pubkey": "abcdef1234567890...",
"created_at": 1675000000,
"tags": [
["e", "video-event-id"],
["m", "featured-comment"], // Example metadata tag
["a", "admin-tag"] // Administrative tag
],
"content": "Highlighted comment for this video."
}
Implementation Details
1. Posting a Comment
To post a comment:
- The client constructs a comment event using NIP-22 for
created_at
validation. - The event includes references to the video (mandatory) and parent comments (optional).
- The event is signed and published to relays.
API Example:
async function postComment(videoId, commentText, parentCommentId = null) {
const event = {
kind: 1311,
pubkey: userPubkey,
created_at: Math.floor(Date.now() / 1000),
tags: [
['e', videoId],
...(parentCommentId ? [['e', parentCommentId]] : []),
],
content: commentText
};
const signedEvent = await nostrClient.signEvent(event);
await nostrClient.pool.publish(nostrClient.relays, signedEvent);
}
2. Reacting to a Comment
Reactions use NIP-25.
API Example:
async function reactToComment(commentId, reaction) {
const event = {
kind: 7,
pubkey: userPubkey,
created_at: Math.floor(Date.now() / 1000),
tags: [['e', commentId]],
content: reaction // Use "+" for upvote, "-" for downvote
};
const signedEvent = await nostrClient.signEvent(event);
await nostrClient.pool.publish(nostrClient.relays, signedEvent);
}
3. Fetching Comments
Comments are retrieved using REQ
messages filtered by the e
tag for the video’s event ID and optionally by parent comment IDs for threading.
API Example:
async function fetchComments(videoId) {
const filter = {
kinds: [1311],
'#e': [videoId],
limit: 100
};
const comments = await nostrClient.pool.list(nostrClient.relays, [filter]);
return comments.sort((a, b) => a.created_at - b.created_at);
}
4. Live Chat for Live Videos
Real-time public chats for live videos use NIP-28.
API Example:
function subscribeToLiveChat(videoId) {
const sub = nostrClient.pool.sub(nostrClient.relays, [
{
kinds: [42],
'#e': [videoId]
}
]);
sub.on('event', event => {
console.log('New chat message:', event);
});
}
5. Metadata Integration
Use NIP-24 to attach metadata to events for administrative or user-specific tags.
Data Flow
- Posting a Comment:
- User creates a comment event.
- Client signs and publishes the event to relays.
- Fetching Comments:
- Client requests comments for a video by filtering events with the
e
tag.
- Client requests comments for a video by filtering events with the
- Reacting to Comments:
- Users react to comments by posting reaction events.
- Live Discussions:
- Live chat messages are sent and received in real-time using NIP-28.
- Metadata Management:
- Metadata is attached during event creation or editing.
UI/UX Considerations
-
Comment Form:
- Input field for comments.
- Button to post comments.
- Optional reply button for threaded comments.
-
Reactions:
- Upvote and downvote icons next to each comment.
- Display reaction counts dynamically.
-
Live Chat:
- Real-time message updates below live videos.
- Highlight important messages using metadata tags.
-
Nested Threading:
- Indent replies to show comment hierarchy.
Testing and Validation
- Validate:
- Posting, retrieving, and displaying threaded comments.
- Reactions and live chat events.
- Metadata tagging.
- Test:
- Pagination for large comment threads.
- Performance under high comment or chat volume.
- Simulate:
- Various timestamp scenarios to ensure NIP-22 compliance.
Benefits
- Decentralized and censorship-resistant.
- Fully interoperable with other Nostr clients and relays.
- Extensible with reactions, live discussions, and metadata features.