# Content Types
This page will cover the various types of content that are supported, and how to present them to Grayjay.

While Grayjay is primarily used for video, it supports various types of video, audio, but also text, images, and articles. In the future more types of content support might be added!

Content can be presented as a feed object, or a detail object. Feed objects are objects you see inside feeds and overviews such as the Home and Subscription tabs. Generally detail objects have an accompanying overview object.

Feed items are often returned in pagers, the following are some plugin methods that expect a pager of feed items:
```
source.getHome()
source.getChannelContents(...)
```
Content details are generally retrieved using
```
source.getContentDetails(url)
```

Note that all detail objects can be considered feed objects, but not the other way around. When you return a detail object in places where feed object is expected, and the user tries to open said item in a detail view, the ```GetContentDetail``` call is skipped, and the item is immediately shown without loading details.





# Feed Types
Feed types represent content in a feed or overview page. Most feed types have both a thumbnail and preview visualization, where they are displayed slightly differently. The plugin is not aware of these differences though.

## PlatformContent
All feed objects inherit PlatformContent, and always have the following properties:
```kotlin
class PlatformContent
{
	id: PlatformID,
	name: String,
	thumbnails: ThumbNails,
	author: PlatformAuthorLink,
	datetime: Int, // (UnixTimeStamp)
	url: String
}
```




## PlatformVideo
A feed object representing a video or audio.
*Usage:*
```javascript
new PlatformVideo({
	id: new PlatformID("SomePlatformName", "SomeId", config.id),
	name: "Some Video Name",
	thumbnails: new Thumbnails([
			new Thumbnail("https://.../...", 720),
			new Thumbnail("https://.../...", 1080),
		]),
	author: new PlatformAuthorLink(
		new PlatformID("SomePlatformName", "SomeAuthorID", config.id), 
		"SomeAuthorName", 
		"https://platform.com/your/channel/url", 
		"../url/to/thumbnail.png"),
	uploadDate: 1696880568,
	duration: 120,
	viewCount: 1234567,
	url: "https://platform.com/your/detail/url",
	isLive: false
});
```

## PlatformPost
A feed object representing a community post with text, and optionally images.

*Usage:*
```javascript
new PlatformPost{
	id: new PlatformID(config.name, item?.id, config.id),
	name: item?.attributes?.title,
	author: getPlatformAuthorLink(item, context),
	datetime: (Date.parse(item?.attributes?.published_at) / 1000),
	url: item?.attributes?.url,
	description: "Description of Post",
	images: ["../url/to/image1.png", "../url/to/image2.png"],
	thumbnails: new Thumbnails([
			new Thumbnail("https://.../...", 720),
			new Thumbnail("https://.../...", 1080),
		])
});
```


## PlatformNestedMediaContent
A feed object representing a link to a different item (often handled by a different plugin). 

An example is a Patreon video, that links to an unlisted Youtube video. If no plugin exists to handle the content, it will be opened in an in-app browser.

A nested item consists of an detail url and optional metadata such as name, description, thumbnails, etc.
*Usage:*
```javascript
new PlatformNestedMediaContent({
	id: new PlatformID("SomePlatformName", "SomeId", config.id),
	name: "Name of content link",
	author: new PlatformAuthorLink(
		new PlatformID("SomePlatformName", "SomeAuthorID", config.id), 
		"SomeAuthorName", 
		"https://platform.com/your/channel/url", 
		"../url/to/thumbnail.png"),,
	datetime: 1696880568,
	url: item?.attributes?.url,
	contentUrl: "https://someplatform.com/detail/url",
	contentName: "OptionalName",
	contentDescription: "OptionalDescription",
	contentProvider: "OptionalPlatformName",
	contentThumbnails: new Thumbnails([
			new Thumbnail("https://.../...", 720),
			new Thumbnail("https://.../...", 1080),
		])
});
```



# Detail Types
Detail types represent content on a detail page.

## PlatformVideoDetails

A detail object representing a video or audio. It inherits PlatformVideo.


### Usage:
```javascript
new PlatformVideoDetails({
	id: new PlatformID("SomePlatformName", "SomeId", config.id),
	name: "Some Video Name",
	thumbnails: new Thumbnails([
			new Thumbnail("https://.../...", 720),
			new Thumbnail("https://.../...", 1080),
		]),
	author: new PlatformAuthorLink(
		new PlatformID("SomePlatformName", "SomeAuthorID", config.id), 
		"SomeAuthorName", 
		"https://platform.com/your/channel/url", 
		"../url/to/thumbnail.png"),
	uploadDate: 1696880568,
	duration: 120,
	viewCount: 1234567,
	url: "https://platform.com/your/detail/url",
	isLive: false,

	description: "Some description",
	video: new VideoSourceDescriptor([]), //See sources
	live: null,
	rating: new RatingLikes(123),
	subtitles: []
});
```
### Live Streams
If your video is live, the ```isLive``` property should be ```true```, and the ```live``` property should be set to a ```HLSSource```, ```DashSource```, or equivelant.

### UnMuxed  and Audio-Only
If your content is either audio-only (eg. music), or has seperate video/audio tracks, you want to use ```UnMuxedVideoDescriptor``` instead of ```VideoSourceDescriptor```:
```javascript
new UnMuxedVideoDescriptor(
	[videoSource1, videoSource2, ...], 
	[audioSource1, audioSource2, ...]
);
```

### Sources
Inside a VideoDescriptor you need to provide an array of sources. 
Below you can find several source types that Grayjay supports:

**Standard Url Video/Audio**
These are videos available directly on a single url.
```javascript
new VideoUrlSource({
	width: 1920,
	height: 1080,
	container: "video/mp4",
	codec: "avc1.4d401e",
	name: "1080p30 mp4",
	bitrate: 188103,
	duration: 250,
	url: "https://platform.com/some/video/url.mp4"
});
//For audio:
new AudioUrlSource({
	container: "audio/mp4",
	codec: "mp4a.40.2",
	name: "mp4a.40.2",
	bitrate: 131294,
	duration: 250,
	url: "https://platform.com/some/video/url.mp4a",
	language: "Unknown"
});
```
**Range Url Video/Audio**
These are more complex url sources that require very specific range headers to function.  They require correct initialization and index positions.
These are converted to Dash manifests.

```javascript
new VideoUrlRangeSource({
	width: 1920,
	height: 1080,
	container: "video/mp4",
	codec: "avc1.4d401e",
	name: "1080p30 mp4",
	bitrate: 188103,
	duration: 250,
	url: "https://platform.com/some/video/url.mp4",
	itagId: 1234, //Optional
	initStart: 0,
	initEnd: 219,
	indexStart: 220,
	indexEnd: 791
});
//For Audio
new AudioUrlRangeSource({
	container: "audio/mp4",
	codec: "mp4a.40.2",
	name: "mp4a.40.2",
	bitrate: 131294,
	duration: 250,
	url: "https://platform.com/some/video/url.mp4a",
	language: "Unknown"
	itagId: 1234, //Optional
	initStart: 0,
	initEnd: 219,
	indexStart: 220,
	indexEnd: 791,
	audioChannels: 2
});
```

**HLSSource**
These are sources that are described in a HLS Manifest. 
```javascript
new HLSSource({
	name: "SomeName", //Optional
	duration: 250, //Optional
	url: "https://platform.com/some/hls/manifest.m3u8",
	priority: false, //Optional
	language: "Unknown" //Optional
});
``` 
Generally, HLS sources deprioritized in Grayjay. However if your platform requires HLS sources to be prioritized, you set ```priority``` to ```true```.

**DashSource**
These are sources that are described in a Dash Manifest. 
```javascript
new DashSource({
	name: "SomeName", //Optional
	duration: 250, //Optional
	url: "https://platform.com/some/dash/manifest.mpd"
});
```

## PlatformPostDetails
A detail object representing a text with optionally accompanying images. The text can be either raw text or html (and possibly in future markup).

### Usage:
```javascript
new PlatformPostDetails{
	id: new PlatformID(config.name, item?.id, config.id),
	name: item?.attributes?.title,
	author: getPlatformAuthorLink(item, context),
	datetime: (Date.parse(item?.attributes?.published_at) / 1000),
	url: item?.attributes?.url,
	description: "Description of Post",
	images: ["../url/to/image1.png", "../url/to/image2.png"],
	thumbnails: new Thumbnails([
			new Thumbnail("https://.../thumbnail1.png", 720),
			new Thumbnail("https://.../thumbnail2.png", 1080),
		]),
	rating: new RatingLikes(123),
	textType: Type.Text.Html/Raw/Markup,
	content: "Your post content in either raw, html, or in future markup."
});
```


