DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • How Spring Boot Starters Integrate With Your Project
  • Integrate Spring With Open AI
  • Upgrade Guide To Spring Boot 3.0 for Spring Data JPA and Querydsl
  • Spring Boot: User Login API Test Client Using Rest Assured

Trending

  • AI Meets Vector Databases: Redefining Data Retrieval in the Age of Intelligence
  • The Human Side of Logs: What Unstructured Data Is Trying to Tell You
  • Hybrid Cloud vs Multi-Cloud: Choosing the Right Strategy for AI Scalability and Security
  • The Cypress Edge: Next-Level Testing Strategies for React Developers
  1. DZone
  2. Coding
  3. Frameworks
  4. YouTube Data API (v3): Introduction With Spring Boot

YouTube Data API (v3): Introduction With Spring Boot

Learn more about app development using the YouTube Data API.

By 
Sanjoy Kumer Deb user avatar
Sanjoy Kumer Deb
DZone Core CORE ·
Sep. 17, 19 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
19.3K Views

Join the DZone community and get the full member experience.

Join For Free

Java YouTube Data API

Learn more about app development using the YouTube Data API

YouTube is a video-sharing website where users can view and upload videos. For both web and app development, sometimes we need to access information from YouTube videos.

You may also like: Build a Spring Boot API Using Spring Data JPA and Hibernate

In this case, we have to use the API's provided by Google developers. The main goal of this article is to introduce how we can use YoutTube APIs with Java. Here, we will use Spring Boot with Hibernate JPA and libraries from Google to implement the example.

Pre-Conditions

To access the YouTube Data API, we have to follow some basic instructions, like create a Google account, a project, credentials, etc. Maybe, it would be better to follow these instructions listed  here .  If we follow the steps from this link, we first need the ClientId, API key, client secret, etc.

Next, we can start our implementation. We need to put our credentials into the application.properties file. To run the GitHub example (link is given below), we also need to set up Java, MySQL, and Gradle.

API Docs

In this article, we are mainly concerned with video information. A YouTube video property mainly contains a channel, duration, description, and statistics (likes, dislikes, etc.). These properties are available in different resources of the YouYube API, such as video, channel, activity, etc. These resources can also perform list, insert, update, and delete operations.

The last part of this tutorial will be to customize the YouYube API so that we can define what we want. Just like the statistics part only contains the number of likes, dislikes, pageviews, etc., the ContentDetails part only contains video definitions, captions, country restrictions, etc.  — and all of these components contain nested objects. Combined, we can get all the properties of a video, but here, we will be focusing on important parts only.

Implementation

With that said, we will be implementing the YouTube Data API in a bit of different way. We will use a REST API to save extracted data to the database. For database entities, we will create a corresponding JPA entity. We have divided most of the video properties depending on a different part. Entities are:

  • YoutubeChannelInfo
  • YouTubeVideoInfo
  • YoutubeVideoStatistics

Additionally, we will have a BaseEntity for common properties, and another entity — CrawlingInfo — to keep track of crawled data.

We will collect the following data for the channel information:

@Entity(name = "youtube_channel")
@Data
@EqualsAndHashCode(callSuper=true)
public class YoutubeChannelInfo extends BaseEntity{

    @Column(name = "channel_id")
    private String channelId;
    @Column(name = "name")
    private String name;
    @Column(name = "subscription_count")
    private long subscriptionCount;
}


For video statistics, we will collect the following data:

@Entity(name = "youtube_video_stat")
@Data
@EqualsAndHashCode(callSuper=true)
public class YoutubeVideoStatistics extends BaseEntity{

    @Column(name = "like_count")
    private long likeCount;

    @Column(name = "dislike_count")
    private long dislikeCount;

    @Column(name = "view_count")
    private long viewCount;

    @Column(name = "favourite_count")
    private long favouriteCount;

    @Column(name = "comment_count")
    private long commentCount;

    @Column(name = "video_id")
    private String videoId;
}


And for common video properties, we will collect the following data:

@Entity(name = "youtube_video_info")
@Data
@EqualsAndHashCode(callSuper=true)
public class YouTubeVideoInfo extends BaseEntity{

    @Column(name = "video_id")
    private String videoId;

    @Column(name = "title")
    private String title;

    @Column(name = "thumbnail_url")
    private String thumbnailUrl;


    @Column(name = "description")
    private String description;

    @Column(name = "published_date")
    private Date publishedDate;

    @Column(name = "definition")
    private String videoDefinition;

    @Column(name = "duration")
    private String videoDuration;

    @Column(name = "caption")
    private String videoCaption;

    @Column(name = "projection")
    private String videoprojection;

    @Column(name = "country_restricted")
    private String countryRestricted;

    @Column(name = "keyword")
    private String keyword;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "channel_id",referencedColumnName = "channel_id")
    private YoutubeChannelInfo channelInfo;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "video_stat_id",referencedColumnName = "video_id")
    private YoutubeVideoStatistics videoStatistics;
}


Now, we will fetch video information through the YouTube Data API. So, we need some libraries provided by the Google team. 

compile group: 'com.google.api-client', name: 'google-api-client', version: '1.25.0'
compile group: 'com.google.apis', name: 'google-api-services-youtube', version: 'v3-rev212-1.25.0'
compile group: 'com.google.apis', name: 'google-api-services-youtubeAnalytics', version: 'v1-rev14-1.13.2-beta'
compile group: 'com.google.apis', name: 'google-api-services-youtubereporting', version: 'v1-rev1-1.20.0'
compile("com.google.oauth-client:google-oauth-client-jetty:1.25.0") {
exclude group: 'org.mortbay.jetty', module: 'servlet-api'
}
compile group: 'com.google.http-client', name: 'google-http-client-jackson2', version: '1.25.0'
compile group: 'com.google.collections', name: 'google-collections', version: '1.0'


Other libraries are also used for Spring Boot and database support. We can find these libraries at gradle file .

At first, we have to initialize  YouTube (v3) properties which supports core YouTube features such as uploading videos, creating and managing playlists, searching for content, and much more. But here, we will first implement some basic properties.

     youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, new HttpRequestInitializer() {
                public void initialize(HttpRequest request) throws IOException {
      }
     }).setApplicationName("YoutubeVideoInfo")
       .setYouTubeRequestInitializer
       (new YouTubeRequestInitializer(env.getProperty("youtube.apikey"))).build();


When I was creating my credentials, I had to create an application name YouTubeVideoInfo that is assigned as application name. The property youtube.apikey is located in the application.properties file. We have to replace youtube.apikey's value with our ones.

Now, we will fetch some information using this. Initially, we use id, snippet to fetch some basic data.

YouTube.Search.List search = youtube.search().list("id,snippet");
//search keyword eg. "IELTS"
search.setQ(queryTerm);
//return only video type data
search.setType("video");
// number of video data return. maximum 50
search.setMaxResults(NUMBER_OF_VIDEOS_RETURNED);


Here, queryTerm will be our search key, and video will be the data type so that it will return video type data information. In a youtube API list request, maximum 50 videos information returns as response.

 SearchListResponse searchResponse = search.execute();

List<SearchResult> searchResultList = searchResponse.getItems();
if (searchResultList != null) {
  extractAndSave(searchResultList.iterator(), queryTerm);
  }

crawlingInfo.setNextPageToken(searchResponse.getNextPageToken());
crawlingInfoService.update(crawlingInfo);
System.out.println("Next Page token : " + searchResponse.getNextPageToken());


Here,  the search.execute() method will return the expected result. So, we have to parse this response. And another thing:  CrawlingInfo class will be used to maintain the next and previous page. The YouTube API returns a maximum of 50 pieces of data in a request with the next page token. If we want to access next page we have to add nextPageToken at pageToken properties on request, then it will move to the next page. That's why we are keeping this track using  crawlingInfo  entity.

We will use more queries on the remaining code to extract channel information, content details, statistics, etc. for every video and then save to the database.

public List<Object> getYoutubeVideoList(String queryTerm,long pageToCrawl) {

        try {

            youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, new HttpRequestInitializer() {
                public void initialize(HttpRequest request) throws IOException {
                }
            }).setApplicationName("YoutubeVideoInfo")
                    .setYouTubeRequestInitializer(new YouTubeRequestInitializer(env.getProperty("youtube.apikey"))).build();

            YouTube.Search.List search = youtube.search().list("id,snippet");


            search.setQ(queryTerm);
            search.setType("video");
            search.setMaxResults(NUMBER_OF_VIDEOS_RETURNED);

            for (int i = 0; i < pageToCrawl; i++) {
                String pageToken = null;
                CrawlingInfo crawlingInfo = crawlingInfoService.getBySearchKey(queryTerm);
                if (crawlingInfo != null && crawlingInfo.getNextPageToken() != null) {
                    pageToken = crawlingInfo.getNextPageToken();
                    count = crawlingInfo.getTotalCount();
                    crawlingInfo.setCurrentPageToken(pageToken);
                } else if (crawlingInfo == null) {
                    crawlingInfo = new CrawlingInfo();
                    count = 0;
                    crawlingInfo.setSearchKey(queryTerm);
                    crawlingInfo.setCurrentPageToken(null);
                }

                if (pageToken != null) {
                    search.setPageToken(pageToken);
                }


                SearchListResponse searchResponse = search.execute();

                List<SearchResult> searchResultList = searchResponse.getItems();
                if (searchResultList != null) {
                    extractAndSave(searchResultList.iterator(), queryTerm);
                }

                crawlingInfo.setNextPageToken(searchResponse.getNextPageToken());

                crawlingInfoService.update(crawlingInfo);

                System.out.println("Next Page token : " + searchResponse.getNextPageToken());
            }
        } catch (GoogleJsonResponseException e) {
            System.err.println("There was a service error: " + e.getDetails().getCode() + " : "
                    + e.getDetails().getMessage());
        } catch (IOException e) {
            System.err.println("There was an IO error: " + e.getCause() + " : " + e.getMessage());
        } catch (Throwable t) {
            t.printStackTrace();
        }
        return null;
    }

private void extractAndSave(Iterator<SearchResult> iteratorSearchResults, String query) throws IOException {

        if (!iteratorSearchResults.hasNext()) {
            System.out.println(" There aren't any results for your query.");
        }

        while (iteratorSearchResults.hasNext()) {

            SearchResult singleVideo = iteratorSearchResults.next();

            System.out.println("Video number = " + count + " Inserting video Information " + singleVideo.getId().getVideoId());
            count++;
            YouTubeVideoInfo youTubeVideoInfo = youtubeVideoInfoService.getByVideoId(singleVideo.getId().getVideoId());

            if (youTubeVideoInfo == null) {
                youTubeVideoInfo = new YouTubeVideoInfo();
                ResourceId rId = singleVideo.getId();

                youTubeVideoInfo.setKeyword(query);
                youTubeVideoInfo.setDescription(singleVideo.getSnippet().getDescription());
                youTubeVideoInfo.setPublishedDate(new Date(singleVideo.getSnippet().getPublishedAt().getValue()));

                if (rId.getKind().equals("youtube#video")) {
                    Thumbnail thumbnail = singleVideo.getSnippet().getThumbnails().getDefault();
                    youTubeVideoInfo.setVideoId(rId.getVideoId());
                    youTubeVideoInfo.setTitle(singleVideo.getSnippet().getTitle());
                    youTubeVideoInfo.setThumbnailUrl(thumbnail.getUrl());

                    youTubeVideoInfo.setChannelInfo(getChannelDetailsById(singleVideo.getSnippet().getChannelId()));

                    youTubeVideoInfo.setVideoStatistics(getVideosStatistics(rId.getVideoId()));
                }

                youtubeVideoInfoService.save(youTubeVideoInfo);
            } else {
                System.out.println("Video Already exists... ");
            }


        }
    }

    private YoutubeChannelInfo getChannelDetailsById(String channelId) throws IOException {
        YouTube.Channels.List channels = youtube.channels().list("snippet, statistics");

        YoutubeChannelInfo youtubeChannelInfo = new YoutubeChannelInfo();
        youtubeChannelInfo.setChannelId(channelId);
        channels.setId(channelId);
        ChannelListResponse channelResponse = channels.execute();
        Channel c = channelResponse.getItems().get(0);

        youtubeChannelInfo.setName(c.getSnippet().getTitle());
        youtubeChannelInfo.setSubscriptionCount(c.getStatistics().getSubscriberCount().longValue());

        YoutubeChannelInfo channelInfo = youtubeChannelService.getByChannelId(channelId);

        if (channelInfo == null) {
            youtubeChannelService.save(youtubeChannelInfo);
        } else {
            return channelInfo;
        }
        return youtubeChannelInfo;
    }


    public YoutubeVideoStatistics getVideosStatistics(String id) throws IOException {
        YouTube.Videos.List list = youtube.videos().list("statistics");
        list.setId(id);
        Video v = list.execute().getItems().get(0);

        YoutubeVideoStatistics statistics = new YoutubeVideoStatistics();

        statistics.setVideoId(id);
        statistics.setLikeCount(v.getStatistics().getLikeCount() !=null ? v.getStatistics().getLikeCount().longValue():0);
        statistics.setDislikeCount(v.getStatistics().getDislikeCount() != null ? v.getStatistics().getDislikeCount().longValue():0);
        statistics.setFavouriteCount(v.getStatistics().getFavoriteCount() != null ? v.getStatistics().getFavoriteCount().longValue():0);
        statistics.setCommentCount(v.getStatistics().getCommentCount() != null ? v.getStatistics().getCommentCount().longValue() : 0);
        statistics.setViewCount(v.getStatistics().getViewCount() != null ? v.getStatistics().getViewCount().longValue() : 0);


        youtubeVideoStatService.save(statistics);

        return statistics;
    }


    public YouTubeVideoInfo getCoontentDetails(String id, YouTubeVideoInfo youTubeVideoInfo) throws IOException {
        YouTube.Videos.List list = youtube.videos().list("contentDetails");
        list.setId(id);
        Video v = list.execute().getItems().get(0);
        youTubeVideoInfo.setVideoDefinition(v.getContentDetails().getDefinition());
        youTubeVideoInfo.setVideoCaption(v.getContentDetails().getCaption());
        youTubeVideoInfo.setVideoprojection(v.getContentDetails().getProjection());
        youTubeVideoInfo.setCountryRestricted(v.getContentDetails().getCountryRestriction().toPrettyString());

        return youTubeVideoInfo;
    }


If we take a look on the previous code snippet, we can see that,  for statistics and contentDetails, we are using videos resources and list operation. And for channel information, we are using channel resources and list operation. Here, I have represented all list operations of the YouTube Data API. And with similar approach, we can use other operations smoothly.

The code examples from this article are available here. 

Further Reading

Build a Spring Boot API Using Spring Data JPA and Hibernate

API Spring Framework Data (computing) Spring Boot

Opinions expressed by DZone contributors are their own.

Related

  • How Spring Boot Starters Integrate With Your Project
  • Integrate Spring With Open AI
  • Upgrade Guide To Spring Boot 3.0 for Spring Data JPA and Querydsl
  • Spring Boot: User Login API Test Client Using Rest Assured

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!