Hi have been working on this project for quite some time, and It has come to the point at which I need to get the channel banner of a user's channel. I have this url (https://i2.ytimg.com/i/zRJMLe36PT0Q2mhlmbU2OQ/1.jpg) that gets the channel avatar of the channel avatar via the channel id. (the id is the long string of text and numbers) I searched the internet for quite some time also, and was at no luck to finding the url. If anyone can find a url that works the same as the avatar, just for the channel banner, I would be greatly appreciated! Thanks, and cheers! (ps, I would rather not use php, but if there is a solution using php, I can use it)
You can get the banner image of a Youtube channel. Where the URL includes the word 'channel' followed by a 24 character string such as: https://www.youtube.com/channel/UCNa8NxMgSm7m4Ii9d4QGk1Q, then the following code will retrieve the banner information and more:
https://www.googleapis.com/youtube/v3/channels?part=brandingSettings&id={CHANNEL_ID}&key={GOOGLE_API_KEY}
Search for 'bannerImageUrl' to speed up the process if you are in a browser.
If you do not have a Google API key, visit the console and create one under the credentials menu. You should remove the curly brackets and not place the channel id or API key between them.
If you want to get the banner image of a YouTube channel with the word 'user' in the URL, such as: https://www.youtube.com/user/cocacola then I am not so sure. The solution on this page did not work for me.
I have just come across this result which shows more information.
Using Java with Jsoup to get the channels header image without using Youtube API:
public final static String YOUTUBE_HEADER_IMAGE_START_URL = "yt3.ggpht.com/";
public final static String YOUTUBE_HEADER_IMAGE_END_URL = "-no-nd-rj";
private void getYoutubeChannelHeaderImage(String channelUrl) throws IOException
{
Document document = Jsoup.connect(channelUrl).userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1").get();
String html = document.toString();
Pattern pattern = Pattern.compile(YOUTUBE_HEADER_IMAGE_START_URL + "(.*?)" + YOUTUBE_HEADER_IMAGE_END_URL, Pattern.DOTALL);
Matcher matcher = pattern.matcher(html);
while (matcher.find()) {
String imgUrl = matcher.group(1);
if (imgUrl.length()<500)
System.out.println("https://" + YOUTUBE_HEADER_IMAGE_START_URL+imgUrl+YOUTUBE_HEADER_IMAGE_END_URL);
}
}
This code will output all available dimensions of a Youtube channel header image.
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w1138-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj // 1138 x 188
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w1707-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj // 1707 x 282
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w2120-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj // 2120 x 350
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w2276-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj // 2276 x 376
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w2560-fcrop64=1,00005a57ffffa5a8-k-c0xffffffff-no-nd-rj // 2560 x 423
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w320-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj // 320 x 180
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w854-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj // 854 x 480
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w1280-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj // 1280 x 720
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w1920-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj // 1920 x 1080
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w2120-fcrop64=1,00000000ffffffff-k-c0xffffffff-no-nd-rj // 2120 x 1192
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w320-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj // 320 x 52
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w640-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj // 640 x 105
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w960-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj // 960 x 158
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w1280-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj // 1280 x 211
https://yt3.ggpht.com/2fCpG8MNmWvT8zz7MBFVlPMOA07bekDqK7FgNrdbh7ldLccLMsU1UwKlI1t3SJ5vxNJoA5pIYw=w1440-fcrop64=1,32b75a57cd48a5a8-k-c0xffffffff-no-nd-rj // 1440 x 238
i found a super quick way to do this. you can find the url in the console. i clicked on my avatar and then selected "my channel" from the nav. from there, click customize channel. now right click somewhere on the image. and then click inspect to open the console. you should now be targeting a div with an id of something like c4-header-bg-container. under the styles tab, there is a background-image attribute for that id. just copy the value inside the url() function. make sure you either remove the leading slashes or prepend https: to them. that is the url of your image. you may now do as thou wilt with it.
Related
Goal: Get all (non-live) videos uploaded on October 2020 order by viewCount
My first try was like this:
request = youtube.search().list(
part="snippet",
order="viewCount",
publishedAfter="2020-10-01T00:00:00Z",
publishedBefore="2020-10-31T23:59:59Z",
type="video",
maxResults=50
)
It returns me YpUR1rHXbqs video which is live (and still running). IMHO it doesn't fit publishedBefore="2020-10-31T23:59:59Z" since it still running, but never mind.
I try to filter out live videos with:
response = request.execute()
for item in response["items"]:
if item["snippet"]["liveBroadcastContent"] != 'live':
It returns o6zDG9jYpC0 with 7 624 725 views today and 'liveBroadcastContent'='none' Seems too little to me.
So I try add q="a" to check if o6zDG9jYpC0 is the most viewed one:
request = youtube.search().list(
q='a',
part="snippet",
order="viewCount",
publishedAfter="2020-10-01T00:00:00Z",
publishedBefore="2020-10-31T23:59:59Z",
type="video",
maxResults=50
)
Returns uy30PB5BpV0 with 192 861 990 views :-( and 'liveBroadcastContent'='none'
I try to experiment with q="", q="*", q="%2A", q="+", q=" ", q=None ... , but no luck.
Adding eventType="completed" seems to work well with missing/not set q but it omits 'liveBroadcastContent'='none' videos.
How can I query all videos please?
Side note: I'm aware of Video: list (most popular videos) chart='mostPopular' but it doesn't support publishedAfter/Before which is required
I have some problems with Facebook sharing. Posted messages look normal via browsers (iOS, PC and Mac versions):
And only FB iOS app shows it wrong:
What could be the reason for this?
UPD:
I tried 200, 600 and 158 pixels images. Result:
My code is:
public LevelUPFeed (int reachedLevel, string pictureURL) //LevelUPFeed : IFeed
{
_linkDescription = string.Format("Just reached Level {0} ", reachedLevel);
_picture = pictureURL;
}
public void SendFeed (IFeed feed, Action<bool> callback)
{
//... callback creating
FB.Feed (
feed.ToId, feed.Link,
feed.LinkName, feed.LinkCaption,
feed.LinkDescription, feed.Picture,
feed.MediaSource, feed.ActionName,
feed.ActionLink, feed.Reference,
feed.Properties, convertedCallback);
}
feed = new LevelUPFeed (level, pictureUrl);
FBManager.SendFeed (feed, onFeedSent);
feed.LinkName is "Game Name", feed.Link "https://facebook.com", feed.LinkName is "Level Up!". All other strings is string.Empty
Picture links:
600px : http://i.imgur.com/10DdiWc.png
200px : http://i.imgur.com/0Smpm6s.png
There are image specifications in the Open Graph Sharing Best Practices documentation. Use PNG or JPG, 72 dpi, at 600 x 600 pixels for a feed image. The Feed Dialog documentation says 200 x 200, but the Games feed is specifically mentioned in the best practices document.
There are two different image sizes to use for game apps:
Open Graph Stories Images appear in a square format. Image ratios for
these apps should be 600 x 600 px. Non-open Graph Stories Images
appear in a rectangular format. You should use a 1.91:1 image ratio,
such as 600 x 314 px.
If this does not answer your question, could you post your API call code?
How do you disable the default action for .torrent files/content-type application/x-bittorrent(eg open with dialog or run program) and instead handle the data in a extension?
There are multiple ways, that all boil down to nsIMimeService/nsIHandlerService and nsIMimeInfo and setting the appropriate nsIHandlerInfo. E.g. see PDF.js making itself the handler for PDF files (by effectively disabling all handler or plugins and implementing a stream converter), or my answer on how to register a web protocol handler (not mime related but protocol related, but the handler info stuff still applies).
Depending on how you'd like to handle things, you may use the nsIHandlerApp-ervied interfaces e.g. to pass the uri (protocols) or file (mime) directly to some local or web application, or implement a full blown stream converter like PDF.js.
In theory, it would be also possible to implement new kinds of nsIHandlerApp-derived interfaces, implementing in particular launchWithURI (protocols) or launchWithFile (mime content types and file extensions (downloads)). However, this is a bit tricky as nsIHandlerService only handles the built-in interfaces.
Based on #nmaiers post this is how you do it:
This is how you do it IF the mime type already exists. If it doesn't exist I don't know how to add it, probably some register function.
For some reason the type for my torrents is application/x-download I have no idea why. If you want info on how I figured that out than I'll tell you. So in the example below I use that as file type.
When we console.log(wrappedHandlerInfo) we see that it looks like this:
so now let's do that enumerate all application handlers (i got this from here: MXR :: gApplicationsPane, and if .type == 'application/x-download' let'sbreak` so we can than play with that object.
var handlerService = Cc['#mozilla.org/uriloader/handler-service;1'].getService(Ci.nsIHandlerService);
var listOfWrappedHandlers = handlerService.enumerate();
var i = 0;
while (listOfWrappedHandlers.hasMoreElements()) {
var wrappedHandlerInfo = listOfWrappedHandlers.getNext().QueryInterface(Ci.nsIHandlerInfo);
console.log(i, 'handler for', wrappedHandlerInfo.type, wrappedHandlerInfo);
if (wrappedHandlerInfo.type == 'application/x-download') {
break;
}
i++;
}
console.log('Listed ', i, ' handlers');
console.log('wrappedHandlerInfo=', wrappedHandlerInfo); //should be the application/x-download one as we broke the loop once it found that
now we have to set its properties then save it.
// Change and save mime handler settings.
wrappedHandlerInfo.alwaysAskBeforeHandling = false;
wrappedHandlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
handlerService.store(wrappedHandlerInfo);
I'm not sure what to change those properties too though, maybe #nmaier can advise us on that.
We see here on MXR :: nsIHandlerService.idl #L69 that store does this:
69 * Save the preferred action, preferred handler, possible handlers, and
70 * always ask properties of the given handler info object to the datastore.
71 * Updates an existing record or creates a new one if necessary.
72 *
73 * Note: if preferred action is undefined or invalid, then we assume
74 * the default value nsIHandlerInfo::useHelperApp.
75 *
76 * #param aHandlerInfo the handler info object
77 */
78 void store(in nsIHandlerInfo aHandlerInfo);
ANOTHER WAY
Ok i found an even better way, this way you don't need to loop to find the handler.
Do this:
var mimeService = Cc['#mozilla.org/mime;1'].getService(Ci.nsIMIMEService);
var CONTENT_TYPE = ''; //'application/x-download'; can leave this blank
var TYPE_EXTENSION = 'torrent';
var handlerInfo = mimeService.getFromTypeAndExtension(CONTENT_TYPE, TYPE_EXTENSION);
console.info('handlerInfo:', handlerInfo); //http://i.imgur.com/dUKox24.png
// Change and save mime handler settings.
handlerInfo.alwaysAskBeforeHandling = false;
handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
handlerService.store(handlerInfo);
This handlerInfo object is slightly different in that it has a primaryExtension attribute which holds torrent.
Problem with both ways
The problem with both ways is that, if the mime type doesn't exist, you have to register it somehow, I don't know how. Probably use mime service and some register function.
Update August 3rd 2014
I think i found a solution for the problem mentioned in bullet above (problem with both ways).
MXR :: addPossibleApplicationHandler
235 addPossibleApplicationHandler: function(aNewHandler) {
236 var possibleApps = this.possibleApplicationHandlers.enumerate();
237 while (possibleApps.hasMoreElements()) {
238 if (possibleApps.getNext().equals(aNewHandler))
239 return;
240 }
241 this.possibleApplicationHandlers.appendElement(aNewHandler, false);
242 },
243
This is code for addPossibleApplicationHandler, we probably just need to copy that and edit somehow.
Update August 3rd 2014
Ok this is how to add protocol handler (it only adds a nsIWebAppHandler but im sure to add a local meaning a nsIAppHandler it should be similar just no need for uri param:
https://gist.github.com/Noitidart/2faaac70c62bc13e7773#add-a-handler-to-a-protocol
Info on functions available in nsIMIMEService: MXR :: nsIMIMEService.idl
I'm trying to get last 5 tweets from a person. I did it, but profile picture is not looking normal, resolution is corrupted. like that. ! http://i.hizliresim.com/wLQEJZ.jpg
var $twitter = $('#twitter');
$.getJSON('http://www.demo.net/twitter.php?username=yeniceriozcan&count=5', function(data){
var total = data.length,
i = 0;
$twitter.html(''); // önce içindekini temizle sonra tweetleri yazdır.
for ( i; i < total; i++ ){
var tweet = data[i].text; // tweet
var date = parseTwitterDate(data[i].created_at); // tarih
var image = data[i].user.profile_image_url; // profil resmi
var url = 'https://twitter.com/' + data[i].user.screen_name +'/status/' + data[i].id_str;
$twitter.append('<div class="tweet"><a target="_blank" href="' + url + '"><img src="' + image + '" alt="" class="profile-image" />' + tweet + '</a> <span class="tweet-date">(' + date + ')</span></div>');
}
});
This is my code. I tried to that for to get profile picture,
var image = data[i].user.profile_image_url;
And also in other tweets file,
$tweets = $twitter->get('https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name='.$username.'&count='.$count);
print json_encode($tweets);
I used this api.
but I can not view pictures in normal resolutions. How can I fix it?
Thanks.
I found that using bigger still brought the picture back in a relatively small format. Using this answer enables you to resize the image allowing you to have a big image without distortion.
If you want to get the image full size just get rid of the "_normal" completely
http://pbs.twimg.com/profile_images/429221067630972918/ABLBUS9o_normal.jpeg
Goes to
http://pbs.twimg.com/profile_images/429221067630972918/ABLBUS9o.jpeg
Note: The urls in this answer are modified so as to not reflect my twitter details hence why entering them will give you a "no page exists"
When you read the url from data[i].user.profile_image_url, replace "_normal" with "_bigger". Here's the explanation from the Twitter docs:
User Profile Images and Banners
Update December 22nd 2020
This is still the case - works.
Update May 6th 2017
When you get the user's profile image via profile_image_url or profile_image_url_https (see User Profile Images and Banners), try to replace "_normal" at the end of the filename with "_400x400".
Seems that they are now scaling images down to 400x400 and then delete the original file.
In case you still need this questions answered (since none of the previous ones are marked as an accepted answer) this is how I managed to deal with the Twitter API image URL sizing:
Grabbing the URL from the API will return the "http" and "https" URL's in the following format(s):
http:
http://pbs.twimg.com/profile_images/378812345851234567/Ay2SHEYz_normal.png
https:
https://pbs.twimg.com/profile_images/378812345851234567/Ay2SHEYz_normal.png
For whatever reason Twitter decided that a 48x48 png was good enough.
If you want the full resolution you need to remove the "_normal" tag from either URL, as angryTurtle stated above. This will give you the URL of the full size image. Here is quick example work around of accomplishing this:
/// remove '_normal' from picture url to get full size
NSString *TWTRPicStringF = [twitterProfilePictureURLStringN stringByReplacingOccurrencesOfString:#"_normal" withString:#""];
Hopefully this helps you and you can mark one of these as the accepted answer to close the question!
FYI: I also have modified the URL contents to protect my own Twitter information, explaining the "no page exists" when using one of the provided URL's above.
Some Background
I have an ASP.net MVC 4 web application which provides access to a large number of photos. Each photo is given a unique ID from a MySQL table which then makes up the filename in hex form and stored in a folder on the file system.
For example:
D:\Photos\69F.jpg
Throughout the application, different sized thumbnails are displayed which are created using the original photo. Since the thumbnails are changed very rarely, if at all, the thumbnails are created and saved to the same file-system folder in the following formats. (This means that 90% of the time, the photo can simply be returned immediately without any image processing).
Thumbnail Normal - D:\Photos\69F_t.jpg
Thumbnail Map - D:\Photos\69F_tm.jpg
All photos are accessed through a special controller (ImageController), this controller has a number of actions depending on the type of thumbnail that is required. For example, if a normal thumbnail is required, the Thumb action must be called which then determines whether the thumbnail exists and if not, creates & saves it before returning it to the browser.
\Image\Thumb\1695
The application is running under an account which has full access to the folder mentioned above and since most of the time this works, this cannot be a permissions issue!
The issue
The problem I have is that I am getting sporadic errors being reported from the application when calls are being made to get thumbnails. The errors all follow the format below, but of course the photo ID changes (i.e., it happens on more than 1 photo):
The process cannot access the file 'D:\Photos\69F_t.jpg' because it is being used by another process.
or...
Access to the path 'D:\Photos\69F_t.jpg' is denied.
The errors above are both originating from Return File(...) line in the final Try...Catch:
Function Thumb(Optional ByVal id As Integer = Nothing)
Dim thumbImage As WebImage
Dim dimension As Integer = 200
' Create the image paths
Dim imageOriginal As String = System.Configuration.ConfigurationManager.AppSettings("imageStore") + Hex(id) + ".jpg"
Dim imageThumb As String = System.Configuration.ConfigurationManager.AppSettings("imageStore") + Hex(id) + "_t.jpg"
' If no image is found, return not found
If FileIO.FileSystem.FileExists(imageOriginal) = False Then
Return New HttpNotFoundResult
End If
' If a thumbnail is present, check its validity and return it
If FileIO.FileSystem.FileExists(imageThumb) = True Then
thumbImage = New WebImage(imageThumb)
' If the dimensions are correct, simply return the image
If thumbImage.Width = dimension Then
thumbImage = Nothing
Return File(imageThumb, System.Net.Mime.MediaTypeNames.Image.Jpeg)
End If
End If
' If we get this far, either the thumbnail is not the right size or does not exist!
thumbImage = New WebImage(imageOriginal)
' First we must make the image a square
If thumbImage.Height > thumbImage.Width Then
' Portrait
Dim intPixelRemove As Integer
' Determine the amount to crop off the top and bottom
intPixelRemove = (thumbImage.Height - thumbImage.Width) / 2
thumbImage.Crop(intPixelRemove, 0, intPixelRemove, 0)
Else
' Landscape
Dim intPixelRemove As Integer
' Determine the amount to crop off the top and bottom
intPixelRemove = (thumbImage.Width - thumbImage.Height) / 2
thumbImage.Crop(0, intPixelRemove, 0, intPixelRemove)
End If
thumbImage.Resize(dimension + 2, dimension + 2, True, True)
thumbImage.Crop(1, 1, 1, 1)
thumbImage.Save(imageThumb)
thumbImage = Nothing
Try
Return File(imageThumb, System.Net.Mime.MediaTypeNames.Image.Jpeg)
Catch ex As Exception
Return New HttpNotFoundResult
End Try
End Function
The questions
I'm pretty sure that something has left the file open so is not letting the application return the file to the browser, but whatever it is, its very sporadic as this works fine on 90-95% of calls.
Either that or the issue is due to concurrency as more than 1 person tries to access the same file.
Can anyone spot what might be causing this?
Am I likely to suffer more issues if multiple people try to access the same photo thumbnail at the same time?